home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / inet.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  73.4 KB  |  2,951 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #if !defined(_WIN32_WCE_NO_WININET)
  13. #include <afxtempl.h>
  14. #include <afxinet.h>
  15.  
  16. #pragma warning(disable: 4706) // assignment within conditional
  17.  
  18. #ifdef AFX_INET_SEG
  19. #pragma code_seg(AFX_INET_SEG)
  20. #endif
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. #define new DEBUG_NEW
  28.  
  29. #if !defined(_WIN32_WCE)
  30. #ifdef _AFXDLL
  31. #pragma comment(lib, "wininet.lib")
  32. #endif
  33. #endif // _WIN32_WCE
  34.  
  35. /////////////////////////////////////////////////////////////////////////////
  36. // non-localized useful strings
  37.  
  38. typedef struct tagServiceTable {
  39.     DWORD dwService;
  40.     LPCTSTR pstrIdentifier;
  41. } SvcTable;
  42.  
  43. AFX_STATIC_DATA const TCHAR _afxURLftp[] = _T("ftp://");
  44. AFX_STATIC_DATA const TCHAR _afxURLgopher[] = _T("gopher://");
  45. AFX_STATIC_DATA const TCHAR _afxURLhttp[] = _T("http://");
  46.  
  47. const LPCTSTR CHttpConnection::szHtmlVerbs[] = {
  48.     _T("POST"),
  49.     _T("GET"),
  50.     _T("HEAD"),
  51.     _T("PUT"),
  52.     _T("LINK"),
  53.     _T("DELETE"),
  54.     _T("UNLINK"),
  55. };
  56.  
  57.  
  58. /////////////////////////////////////////////////////////////////////////////
  59. // map of HINTERNETs to CInternetSessions* for callbacks
  60.  
  61. // forward declared because we need a #pragma -- see end of this file
  62.  
  63. class CSessionMapPtrToPtr : public CMapPtrToPtr
  64. {
  65. private:
  66.     CCriticalSection m_sect;
  67.  
  68. public:
  69.     CSessionMapPtrToPtr() { }
  70.     ~CSessionMapPtrToPtr() { }
  71.  
  72.     void SetAt(HINTERNET hInternet, CInternetSession* pSess)
  73.     {
  74.         m_sect.Lock();
  75.         CMapPtrToPtr::SetAt(hInternet, pSess);
  76.         m_sect.Unlock();
  77.     }
  78.  
  79.     void RemoveKey(HINTERNET hInternet)
  80.     {
  81.         m_sect.Lock();
  82.         CMapPtrToPtr::RemoveKey(hInternet);
  83.         m_sect.Unlock();
  84.     }
  85.  
  86.     BOOL Lookup(HINTERNET hInternet, CInternetSession*& refpSession)
  87.     {
  88.         BOOL bRet;
  89.         m_sect.Lock();
  90.         bRet = CMapPtrToPtr::Lookup(hInternet, (void*&) refpSession);
  91.         m_sect.Unlock();
  92.         return bRet;
  93.     }
  94. };
  95.  
  96. extern CSessionMapPtrToPtr _afxSessionMap;
  97.  
  98.  
  99. /////////////////////////////////////////////////////////////////////////////
  100. // Global Functions
  101.  
  102. AFX_STATIC BOOL AFXAPI _AfxParseURLWorker(LPCTSTR pstrURL,
  103.     LPURL_COMPONENTS lpComponents, DWORD& dwServiceType,
  104.     INTERNET_PORT& nPort, DWORD dwFlags)
  105. {
  106.     // this function will return bogus stuff if lpComponents
  107.     // isn't set up to copy the components
  108.  
  109.     ASSERT(lpComponents != NULL && pstrURL != NULL);
  110.     if (lpComponents == NULL || pstrURL == NULL)
  111.         return FALSE;
  112.     ASSERT(lpComponents->dwHostNameLength == 0 ||
  113.             lpComponents->lpszHostName != NULL);
  114.     ASSERT(lpComponents->dwUrlPathLength == 0 ||
  115.             lpComponents->lpszUrlPath != NULL);
  116.     ASSERT(lpComponents->dwUserNameLength == 0 ||
  117.             lpComponents->lpszUserName != NULL);
  118.     ASSERT(lpComponents->dwPasswordLength == 0 ||
  119.             lpComponents->lpszPassword != NULL);
  120.  
  121.     ASSERT(AfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
  122.  
  123.     LPTSTR pstrCanonicalizedURL;
  124.     TCHAR szCanonicalizedURL[INTERNET_MAX_URL_LENGTH];
  125.     DWORD dwNeededLength = INTERNET_MAX_URL_LENGTH;
  126.     BOOL bRetVal;
  127.     BOOL bMustFree = FALSE;
  128.     DWORD dwCanonicalizeFlags = dwFlags &
  129.         (ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META |
  130.         ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE);
  131.     DWORD dwCrackFlags = dwFlags & (ICU_ESCAPE | ICU_USERNAME);
  132.  
  133.     bRetVal = InternetCanonicalizeUrl(pstrURL, szCanonicalizedURL,
  134.         &dwNeededLength, dwCanonicalizeFlags);
  135.  
  136.     if (!bRetVal)
  137.     {
  138.         if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  139.             return FALSE;
  140.  
  141.         pstrCanonicalizedURL = new TCHAR[dwNeededLength];
  142.         bMustFree = TRUE;
  143.         bRetVal = InternetCanonicalizeUrl(pstrURL, pstrCanonicalizedURL,
  144.             &dwNeededLength, dwCanonicalizeFlags);
  145.         if (!bRetVal)
  146.         {
  147.             delete [] pstrCanonicalizedURL;
  148.             return FALSE;
  149.         }
  150.     }
  151.     else
  152.         pstrCanonicalizedURL = szCanonicalizedURL;
  153.  
  154.     // now that it's safely canonicalized, crack it
  155.  
  156.     bRetVal = InternetCrackUrl(pstrCanonicalizedURL, 0,
  157.                         dwCrackFlags, lpComponents);
  158.     if (bMustFree)
  159.         delete [] pstrCanonicalizedURL;
  160.  
  161.     // convert to MFC-style service ID
  162.  
  163.     if (!bRetVal)
  164.         dwServiceType = AFX_INET_SERVICE_UNK;
  165.     else
  166.     {
  167.         nPort = lpComponents->nPort;
  168.         switch (lpComponents->nScheme)
  169.         {
  170.         case INTERNET_SCHEME_FTP:
  171.             dwServiceType = AFX_INET_SERVICE_FTP;
  172.             break;
  173.  
  174.         case INTERNET_SCHEME_GOPHER:
  175.             dwServiceType = AFX_INET_SERVICE_GOPHER;
  176.             break;
  177.  
  178.         case INTERNET_SCHEME_HTTP:
  179.             dwServiceType = AFX_INET_SERVICE_HTTP;
  180.             break;
  181.  
  182.         case INTERNET_SCHEME_HTTPS:
  183.             dwServiceType = AFX_INET_SERVICE_HTTPS;
  184.             break;
  185.  
  186.         case INTERNET_SCHEME_FILE:
  187.             dwServiceType = AFX_INET_SERVICE_FILE;
  188.             break;
  189.  
  190.         case INTERNET_SCHEME_NEWS:
  191.             dwServiceType = AFX_INET_SERVICE_NNTP;
  192.             break;
  193.  
  194.         case INTERNET_SCHEME_MAILTO:
  195.             dwServiceType = AFX_INET_SERVICE_MAILTO;
  196.             break;
  197.  
  198.         default:
  199.             dwServiceType = AFX_INET_SERVICE_UNK;
  200.         }
  201.     }
  202.  
  203.     return bRetVal;
  204. }
  205.  
  206. BOOL AFXAPI AfxParseURLEx(LPCTSTR pstrURL, DWORD& dwServiceType,
  207.     CString& strServer, CString& strObject, INTERNET_PORT& nPort,
  208.     CString& strUsername, CString& strPassword, DWORD dwFlags/* = 0*/)
  209. {
  210.     dwServiceType = AFX_INET_SERVICE_UNK;
  211.  
  212.     ASSERT(pstrURL != NULL);
  213.     if (pstrURL == NULL)
  214.         return FALSE;
  215.  
  216.     URL_COMPONENTS urlComponents;
  217.     memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  218.     urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  219.  
  220.     urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
  221.     urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_HOST_NAME_LENGTH+1);
  222.     urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
  223.     urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_PATH_LENGTH+1);
  224.     urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
  225.     urlComponents.lpszUserName = strUsername.GetBuffer(INTERNET_MAX_USER_NAME_LENGTH+1);
  226.     urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
  227.     urlComponents.lpszPassword = strPassword.GetBuffer(INTERNET_MAX_PASSWORD_LENGTH+1);
  228.  
  229.     BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  230.                     dwServiceType, nPort, dwFlags);
  231.  
  232.     strServer.ReleaseBuffer();
  233.     strObject.ReleaseBuffer();
  234.     strUsername.ReleaseBuffer();
  235.     strPassword.ReleaseBuffer();
  236.     return bRetVal;
  237. }
  238.  
  239. BOOL AFXAPI AfxParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,
  240.     CString& strServer, CString& strObject, INTERNET_PORT& nPort)
  241. {
  242.     dwServiceType = AFX_INET_SERVICE_UNK;
  243.  
  244.     ASSERT(pstrURL != NULL);
  245.     if (pstrURL == NULL)
  246.         return FALSE;
  247.  
  248.     URL_COMPONENTS urlComponents;
  249.     memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  250.     urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  251.  
  252.     urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
  253.     urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  254.     urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
  255.     urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  256.  
  257.     BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  258.                     dwServiceType, nPort, ICU_BROWSER_MODE);
  259.  
  260.     strServer.ReleaseBuffer();
  261.     strObject.ReleaseBuffer();
  262.     return bRetVal;
  263. }
  264.  
  265.  
  266. DWORD AFXAPI AfxGetInternetHandleType(HINTERNET hQuery)
  267. {
  268.     DWORD dwServiceType;
  269.     DWORD dwTypeLen = sizeof(dwServiceType);
  270.     if (hQuery == NULL ||
  271.         !InternetQueryOption(hQuery, INTERNET_OPTION_HANDLE_TYPE,
  272.             &dwServiceType, &dwTypeLen))
  273.         return AFX_INET_SERVICE_UNK;
  274.     else
  275.         return dwServiceType;
  276. }
  277.  
  278. AFX_STATIC BOOL AFXAPI 
  279. _AfxQueryCStringInternetOption(HINTERNET hHandle, DWORD dwOption, CString& refString)
  280. {
  281.     DWORD dwLength = 0;
  282.     LPTSTR pstrBuffer;
  283.  
  284.     if (hHandle == NULL)
  285.         return FALSE;
  286.  
  287.     if (!InternetQueryOption(hHandle, dwOption, NULL, &dwLength) &&
  288.         GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  289.     {
  290.         refString.Empty();
  291.         return FALSE;
  292.     }
  293.  
  294.     pstrBuffer = refString.GetBuffer(dwLength);
  295.     BOOL bRet = InternetQueryOption(hHandle, dwOption, pstrBuffer, &dwLength);
  296.     refString.ReleaseBuffer();
  297.     return bRet;
  298. }
  299.  
  300. #ifdef _DEBUG
  301. void AFXAPI AfxInternetStatusCallbackDebug(HINTERNET hInternet,
  302.     DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  303.     DWORD dwStatusInformationLength)
  304. {
  305.     UNUSED_ALWAYS(hInternet);
  306.     TRACE1("Internet ctxt=%d: ", dwContext);
  307.  
  308.     switch (dwInternetStatus)
  309.     {
  310.     case INTERNET_STATUS_RESOLVING_NAME:
  311.         TRACE1("resolving name for %s\n", lpvStatusInformation);
  312.         break;
  313.  
  314.     case INTERNET_STATUS_NAME_RESOLVED:
  315.         TRACE1("resolved name for %s!\n", lpvStatusInformation);
  316.         break;
  317.  
  318.     case INTERNET_STATUS_HANDLE_CREATED:
  319.         TRACE1("handle %8.8X created\n", hInternet);
  320.         break;
  321.  
  322.     case INTERNET_STATUS_CONNECTING_TO_SERVER:
  323.         {
  324.         sockaddr* pSockAddr = (sockaddr*) lpvStatusInformation;
  325.         TRACE1("connecting to socket address \"%s\"\n", pSockAddr->sa_data);
  326.         }
  327.         break;
  328.  
  329.     case INTERNET_STATUS_REQUEST_SENT:
  330.         TRACE0("request sent!\n");
  331.         break;
  332.  
  333.     case INTERNET_STATUS_SENDING_REQUEST:
  334.         TRACE0("sending request...\n");
  335.         break;
  336.  
  337.     case INTERNET_STATUS_CONNECTED_TO_SERVER:
  338.         TRACE0("connected to socket address!\n");
  339.         break;
  340.  
  341.     case INTERNET_STATUS_RECEIVING_RESPONSE:
  342.         TRACE0("receiving response...\n");
  343.         break;
  344.  
  345.     case INTERNET_STATUS_RESPONSE_RECEIVED:
  346.         TRACE0("response received!\n");
  347.         break;
  348.  
  349.     case INTERNET_STATUS_CLOSING_CONNECTION:
  350.         TRACE1("closing connection %8.8X\n", hInternet);
  351.         break;
  352.  
  353.     case INTERNET_STATUS_CONNECTION_CLOSED:
  354.         TRACE1("connection %8.8X closed!\n", hInternet);
  355.         break;
  356.  
  357.     case INTERNET_STATUS_HANDLE_CLOSING:
  358.         TRACE1("handle %8.8X closed!\n", hInternet);
  359.         break;
  360.  
  361.     case INTERNET_STATUS_REQUEST_COMPLETE:
  362.         if (dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT))
  363.         {
  364.             INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
  365.             TRACE2("request complete, dwResult = %8.8X, dwError = %8.8X\n",
  366.                 pResult->dwResult, pResult->dwError);
  367.         }
  368.         else
  369.             TRACE0("request complete.\n");
  370.         break;
  371.  
  372.     case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
  373.     case INTERNET_STATUS_REDIRECT:
  374.     default:
  375.         TRACE1("Unknown status: %d\n", dwInternetStatus);
  376.         break;
  377.     }
  378.  
  379.     return;
  380. }
  381. #endif // _DEBUG
  382.  
  383. void AFXAPI AfxInternetStatusCallback(HINTERNET hInternet, DWORD dwContext,
  384.     DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  385.     DWORD dwStatusInformationLength)
  386. {
  387.     CInternetSession* pSession;
  388.  
  389. #ifdef _DEBUG
  390.     if (afxTraceFlags & traceInternet)
  391.         AfxInternetStatusCallbackDebug(hInternet, dwContext,
  392.             dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
  393. #endif
  394.  
  395.     if (_afxSessionMap.Lookup(hInternet, pSession))
  396.     {
  397.         pSession->OnStatusCallback(dwContext, dwInternetStatus,
  398.             lpvStatusInformation, dwStatusInformationLength);
  399.     }
  400.  
  401.     // note that an entry we can't match is simply ignored as
  402.     // WININET can send notifications for handles that we can't
  403.     // see -- such as when using InternetOpenURL()
  404. }
  405.  
  406.  
  407. /////////////////////////////////////////////////////////////////////////////
  408. // CInternetSession
  409.  
  410. CInternetSession::~CInternetSession()
  411. {
  412.     Close();
  413. }
  414.  
  415. CInternetSession::CInternetSession(LPCTSTR pstrAgent /* = NULL */,
  416.     DWORD dwContext /* = 1 */,
  417.     DWORD dwAccessType /* = PRE_CONFIG_INTERNET_ACCESS */,
  418.     LPCTSTR pstrProxyName /* = NULL */,
  419.     LPCTSTR pstrProxyBypass /* = NULL */,
  420.     DWORD dwFlags /* = 0 */)
  421. {
  422. #if defined(_WIN32_WCE)
  423.     ASSERT(dwFlags == 0);
  424. #else // _WIN32_WCE
  425.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  426. #endif // _WIN32_WCE
  427.     m_bCallbackEnabled = FALSE;
  428.     m_pOldCallback = NULL;
  429.  
  430.     m_dwContext = dwContext;
  431.     if (pstrAgent == NULL)
  432.         pstrAgent = AfxGetAppName();
  433.     m_hSession = InternetOpen(pstrAgent, dwAccessType,
  434.         pstrProxyName, pstrProxyBypass, dwFlags);
  435.  
  436.     if (m_hSession == NULL)
  437.         AfxThrowInternetException(m_dwContext);
  438.     else
  439.         _afxSessionMap.SetAt(m_hSession, this);
  440.  
  441. #if defined(_WIN32_WCE)
  442.     if((dwContext != 0) && (m_hSession != NULL))
  443.         EnableStatusCallback(TRUE);
  444. #endif // _WIN32_WCE
  445. }
  446.  
  447. void CInternetSession::Close()
  448. {
  449.     if (m_bCallbackEnabled)
  450.         EnableStatusCallback(FALSE);
  451.  
  452.     if (m_hSession != NULL)
  453.     {
  454.         InternetCloseHandle(m_hSession);
  455.         _afxSessionMap.RemoveKey(m_hSession);
  456.         m_hSession = NULL;
  457.     }
  458. }
  459.  
  460. #if !defined(_WIN32_WCE)
  461. CGopherConnection* CInternetSession::GetGopherConnection(LPCTSTR pstrServer,
  462.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  463.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  464. {
  465.     ASSERT(AfxIsValidString(pstrServer));
  466.  
  467.     CGopherConnection* pReturn = new CGopherConnection(this,
  468.         pstrServer, pstrUserName, pstrPassword, m_dwContext, nPort);
  469.     return pReturn;
  470. }
  471. #endif // _WIN32_WCE
  472.  
  473. #if !defined(_WIN32_WCE_NO_FTP)
  474. CFtpConnection* CInternetSession::GetFtpConnection(LPCTSTR pstrServer,
  475.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  476.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  477.     BOOL bPassive /* = FALSE */)
  478. {
  479.     ASSERT(AfxIsValidString(pstrServer));
  480.  
  481.     CFtpConnection* pReturn = new CFtpConnection(this,
  482.         pstrServer, pstrUserName, pstrPassword, m_dwContext,
  483.         nPort, bPassive);
  484.     return pReturn;
  485. }
  486. #endif // _WIN32_WCE_NO_FTP
  487.  
  488. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  489.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  490.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  491. {
  492.     ASSERT(AfxIsValidString(pstrServer));
  493.  
  494.     CHttpConnection* pReturn = new CHttpConnection(this,
  495.         pstrServer, nPort, pstrUserName, pstrPassword, m_dwContext);
  496.     return pReturn;
  497. }
  498.  
  499. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  500.     DWORD dwFlags, INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  501.     LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  502. {
  503.     ASSERT(AfxIsValidString(pstrServer));
  504.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  505.  
  506.     CHttpConnection* pReturn = new CHttpConnection(this, pstrServer,
  507.             dwFlags, nPort, pstrUserName, pstrPassword, m_dwContext);
  508.     return pReturn;
  509. }
  510.  
  511. CStdioFile* CInternetSession::OpenURL(LPCTSTR pstrURL,
  512.     DWORD dwContext /* = 0 */, DWORD dwFlags /* = INTERNET_FLAG_TRANSFER_BINARY */,
  513.     LPCTSTR pstrHeaders /* = NULL */, DWORD dwHeadersLength /* = 0 */)
  514. {
  515.     ASSERT(AfxIsValidString(pstrURL));
  516.     ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL);
  517.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  518.  
  519.     // must have TRANSFER_BINARY or TRANSFER_ASCII but not both
  520. #define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII)
  521.     ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0);
  522.     ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK);
  523. #if defined(_WIN32_WCE)
  524.     ASSERT( (dwFlags & ~(_AFX_TRANSFER_MASK | INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_AUTO_REDIRECT)) == 0 );
  525. #endif
  526.     if (dwContext == 1)
  527.         dwContext = m_dwContext;
  528.  
  529.     DWORD dwServiceType;
  530.     CString strServer;
  531.     CString strObject;
  532.     INTERNET_PORT nPort;
  533.     CStdioFile* pReturn;
  534.  
  535.     BOOL bParsed = AfxParseURL(pstrURL, dwServiceType, strServer, strObject, nPort);
  536.  
  537.     // if it turns out to be a file...
  538.     if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE)
  539.     {
  540.         int nMode = CFile::modeRead | CFile::shareCompat;
  541.         if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY)
  542.             nMode |= CFile::typeBinary;
  543.         else
  544.             nMode |= CFile::typeText;
  545.  
  546.         pReturn = new CStdioFile(strObject, nMode);
  547.     }
  548.     else
  549.     {
  550.         HINTERNET hOpener;
  551.  
  552.         dwFlags &= ~(INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII);
  553.         hOpener = InternetOpenUrl(m_hSession, pstrURL, pstrHeaders,
  554.             dwHeadersLength, dwFlags, dwContext);
  555.  
  556.         if (hOpener == NULL)
  557.             AfxThrowInternetException(m_dwContext);
  558.  
  559.         if (!bParsed)
  560.             dwServiceType = AfxGetInternetHandleType(hOpener);
  561.  
  562.         switch (dwServiceType)
  563.         {
  564. #if !defined(_WIN32_WCE)
  565.             case INTERNET_HANDLE_TYPE_GOPHER_FILE:
  566.             case AFX_INET_SERVICE_GOPHER:
  567.             //WINBUG: WININET supplies no way to
  568.             // convert from a URL to a Gopher locator
  569.                 pReturn = new CGopherFile(hOpener, m_hSession, _T(""),
  570.                     0, dwContext);
  571.                 _afxSessionMap.SetAt(hOpener, this);
  572.                 break;
  573. #endif // _WIN32_WCE
  574.  
  575. #if !defined(_WIN32_WCE_NO_FTP)
  576.             case INTERNET_HANDLE_TYPE_FTP_FILE:
  577.             case AFX_INET_SERVICE_FTP:
  578.                 pReturn = new CInternetFile(hOpener, m_hSession, strObject,
  579.                     strServer, dwContext, TRUE);
  580.                 _afxSessionMap.SetAt(hOpener, this);
  581.                 break;
  582. #endif // _WIN32_WCE_NO_FTP
  583.  
  584.             case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
  585.             case AFX_INET_SERVICE_HTTP:
  586.             case AFX_INET_SERVICE_HTTPS:
  587.                 pReturn = new CHttpFile(hOpener, m_hSession, strObject, strServer,
  588.                     CHttpConnection::szHtmlVerbs[CHttpConnection::HTTP_VERB_GET],
  589.                     dwContext);
  590.                 _afxSessionMap.SetAt(hOpener, this);
  591.                 break;
  592.  
  593.             default:
  594.                 TRACE1("Error: Unidentified service type: %8.8X\n", dwServiceType);
  595.                 pReturn = NULL;
  596.         }
  597.     }
  598.  
  599.     return pReturn;
  600. }
  601.  
  602. BOOL CInternetSession::SetOption(DWORD dwOption, LPVOID lpBuffer,
  603.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  604. {
  605.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  606.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  607.         dwOption <= INTERNET_LAST_OPTION);
  608.     ASSERT(dwBufferLength != 0);
  609.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  610.  
  611.     // bogus flag?
  612.     ASSERT(dwFlags == 0 || WCE_IF(FALSE, ((dwFlags & ISO_VALID_FLAGS) == dwFlags)));
  613.  
  614.     return WCE_FCTN(InternetSetOptionEx)(m_hSession, dwOption,
  615.         lpBuffer, dwBufferLength, dwFlags);
  616. }
  617.  
  618. BOOL CInternetSession::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  619.     LPDWORD lpdwBufferLength) const
  620. {
  621.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  622.         dwOption <= INTERNET_LAST_OPTION);
  623.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  624.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  625.     ASSERT(*lpdwBufferLength != 0);
  626.  
  627.     return InternetQueryOption(m_hSession, dwOption,
  628.         lpBuffer, lpdwBufferLength);
  629. }
  630.  
  631. BOOL CInternetSession::QueryOption(DWORD dwOption, DWORD& dwValue) const
  632. {
  633.     DWORD dwLen = sizeof(DWORD);
  634.     return InternetQueryOption(m_hSession, dwOption,
  635.         &dwValue, &dwLen);
  636. }
  637.  
  638. BOOL CInternetSession::QueryOption(DWORD dwOption, CString& refString) const
  639. {
  640.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  641.         dwOption <= INTERNET_LAST_OPTION);
  642.  
  643.     return _AfxQueryCStringInternetOption(m_hSession, dwOption, refString);
  644. }
  645.  
  646. void CInternetSession::OnStatusCallback(DWORD dwContext,
  647.     DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  648.     DWORD dwStatusInformationLength)
  649. {
  650.     ASSERT(m_bCallbackEnabled != NULL);
  651.  
  652.     if (m_pOldCallback != NULL)
  653.     {
  654.         (*m_pOldCallback)(m_hSession, dwContext, dwInternetStatus,
  655.             lpvStatusInformation, dwStatusInformationLength);
  656.     }
  657. }
  658.  
  659. BOOL CInternetSession::EnableStatusCallback(BOOL bEnable /* = TRUE */)
  660. {
  661.     ASSERT(!bEnable || m_hSession != NULL);
  662.     if (m_hSession == NULL)
  663.         return FALSE;
  664.  
  665.     BOOL bResult = TRUE;
  666.  
  667.     if (bEnable)
  668.     {
  669. #if !defined(_WIN32_WCE)
  670.         ASSERT(!m_bCallbackEnabled);
  671. #endif // _WIN32_WCE
  672.         if (!m_bCallbackEnabled)
  673.         {
  674.             INTERNET_STATUS_CALLBACK pRet =
  675.                 InternetSetStatusCallback(m_hSession, AfxInternetStatusCallback);
  676.  
  677.             if (pRet != INTERNET_INVALID_STATUS_CALLBACK)
  678.             {
  679.                 m_pOldCallback = pRet;
  680.                 m_bCallbackEnabled = TRUE;
  681.             }
  682.             else
  683.                 AfxThrowInternetException(m_dwContext);
  684.         }
  685.     }
  686.     else
  687.     {
  688.         ASSERT(m_bCallbackEnabled);
  689.  
  690.         if (m_bCallbackEnabled)
  691.         {
  692.             InternetSetStatusCallback(m_hSession, NULL);
  693.             m_bCallbackEnabled = FALSE;
  694.         }
  695.     }
  696.  
  697.     return bResult;
  698. }
  699.  
  700. #if !defined(_WIN32_WCE)
  701. BOOL CInternetSession::SetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPCTSTR pstrCookieData)
  702. {
  703.     ASSERT(AfxIsValidString(pstrUrl));
  704.     ASSERT(AfxIsValidString(pstrCookieName));
  705.     return InternetSetCookie(pstrUrl, pstrCookieName, pstrCookieData);
  706. }
  707.  
  708. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPTSTR pstrCookieData, DWORD dwBufLen)
  709. {
  710.     ASSERT(AfxIsValidString(pstrUrl));
  711.     ASSERT(AfxIsValidString(pstrCookieName));
  712.     ASSERT(pstrCookieData != NULL);
  713.     return InternetGetCookie(pstrUrl, pstrCookieName, pstrCookieData, &dwBufLen);
  714. }
  715.  
  716. DWORD CInternetSession::GetCookieLength(LPCSTR pstrUrl, LPCTSTR pstrCookieName)
  717. {
  718.     ASSERT(AfxIsValidString(pstrUrl));
  719.     ASSERT(AfxIsValidString(pstrCookieName));
  720.  
  721.     DWORD dwRet;
  722.     if (!InternetGetCookie(pstrUrl, pstrCookieName, NULL, &dwRet))
  723.         dwRet = 0;
  724.     return dwRet;
  725. }
  726.  
  727. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, CString& strCookieData)
  728. {
  729.     ASSERT(AfxIsValidString(pstrUrl));
  730.     ASSERT(AfxIsValidString(pstrCookieName));
  731.  
  732.     DWORD dwLen = GetCookieLength(pstrUrl, pstrCookieName);
  733.  
  734.     LPTSTR pstrTarget = strCookieData.GetBuffer(dwLen+1);
  735.     BOOL bRetVal = InternetGetCookie(pstrUrl, pstrCookieName, pstrTarget, &dwLen);
  736.     strCookieData.ReleaseBuffer(dwLen);
  737.  
  738.     if (!bRetVal)
  739.         strCookieData.Empty();
  740.     return bRetVal;
  741. }
  742. #endif // _WIN32_WCE
  743.  
  744. #ifdef _DEBUG
  745. void CInternetSession::Dump(CDumpContext& dc) const
  746. {
  747.     CObject::Dump(dc);
  748.     dc << "m_hSession = " << m_hSession;
  749.     dc << "\nm_dwContext = " << m_dwContext;
  750. }
  751. #endif
  752.  
  753.  
  754. /////////////////////////////////////////////////////////////////////////////
  755. // Internet Files
  756.  
  757. CInternetFile::CInternetFile(HINTERNET hFile, HINTERNET /* hSession */,
  758.     LPCTSTR pstrFileName, LPCTSTR pstrServer, DWORD dwContext, BOOL bReadMode)
  759.     : m_dwContext(dwContext)
  760. {
  761.     // caller must set _afxSessionMap()!
  762.  
  763.     ASSERT(AfxIsValidString(pstrServer));
  764.     ASSERT(AfxIsValidString(pstrFileName));
  765.     ASSERT(hFile != NULL);
  766.  
  767.     m_strFileName = pstrFileName;
  768.     m_strServerName = pstrServer;
  769.  
  770.     m_hFile = hFile;
  771.     m_bReadMode = bReadMode;
  772.  
  773.     m_pbReadBuffer = NULL;
  774.     m_pbWriteBuffer = NULL;
  775.  
  776.     m_nReadBufferSize = 0;
  777.     m_nReadBufferPos = 0;
  778.     m_nWriteBufferSize = 0;
  779.     m_nWriteBufferPos = 0;
  780.     m_nReadBufferBytes = 0;
  781. }
  782.  
  783. CInternetFile::CInternetFile(HINTERNET hFile,
  784.     LPCTSTR pstrFileName, CInternetConnection* pConnection, BOOL bReadMode)
  785. {
  786.     ASSERT(AfxIsValidString(pstrFileName));
  787.     ASSERT(pConnection != NULL);
  788.     ASSERT_VALID(pConnection);
  789.     ASSERT(hFile != NULL);
  790.  
  791.     _afxSessionMap.SetAt(hFile, pConnection->GetSession());
  792.  
  793.     m_strFileName = pstrFileName;
  794.  
  795.     m_dwContext = pConnection->GetContext();
  796.     m_strServerName = pConnection->GetServerName();
  797.     m_hFile = hFile;
  798.     m_bReadMode = bReadMode;
  799.  
  800.     m_pbReadBuffer = NULL;
  801.     m_pbWriteBuffer = NULL;
  802.  
  803.     m_nReadBufferSize = 0;
  804.     m_nReadBufferPos = 0;
  805.     m_nWriteBufferSize = 0;
  806.     m_nWriteBufferPos = 0;
  807.     m_nReadBufferBytes = 0;
  808. }
  809.  
  810. BOOL CInternetFile::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  811.     LPDWORD lpdwBufferLength) const
  812. {
  813.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  814.         dwOption <= INTERNET_LAST_OPTION);
  815.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  816.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  817.     ASSERT(*lpdwBufferLength != 0);
  818.     ASSERT(m_hFile != NULL);
  819.  
  820.     return InternetQueryOption(m_hFile, dwOption,
  821.         lpBuffer, lpdwBufferLength);
  822. }
  823.  
  824. BOOL CInternetFile::QueryOption(DWORD dwOption, DWORD& dwValue) const
  825. {
  826.     ASSERT(m_hFile != NULL);
  827.  
  828.     DWORD dwLen = sizeof(DWORD);
  829.     return InternetQueryOption(m_hFile, dwOption,
  830.         &dwValue, &dwLen);
  831. }
  832.  
  833. BOOL CInternetFile::QueryOption(DWORD dwOption, CString& refString) const
  834. {
  835.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  836.         dwOption <= INTERNET_LAST_OPTION);
  837.     ASSERT(m_hFile != NULL);
  838.  
  839.     return _AfxQueryCStringInternetOption(m_hFile, dwOption, refString);
  840. }
  841.  
  842. BOOL CInternetFile::SetOption(DWORD dwOption, LPVOID lpBuffer,
  843.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  844. {
  845.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  846.         dwOption <= INTERNET_LAST_OPTION);
  847.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  848.     ASSERT(dwBufferLength != 0);
  849.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  850.  
  851.     // bogus flag?
  852.     ASSERT(dwFlags == 0 || WCE_IF(FALSE, ((dwFlags & ISO_VALID_FLAGS) == dwFlags)));
  853.  
  854.     return WCE_FCTN(InternetSetOptionEx)(m_hFile, dwOption,
  855.         lpBuffer, dwBufferLength, dwFlags);
  856. }
  857.  
  858. BOOL CInternetFile::SetReadBufferSize(UINT nReadSize)
  859. {
  860.     ASSERT_VALID(this);
  861.     BOOL bRet = TRUE;
  862.  
  863.     if (nReadSize != -1 && nReadSize != m_nReadBufferSize)
  864.     {
  865.         if (m_nReadBufferPos > nReadSize)
  866.             bRet = FALSE;
  867.         else
  868.         {
  869.             if (nReadSize == 0)
  870.             {
  871.                 delete [] m_pbReadBuffer;
  872.                 m_pbReadBuffer = NULL;
  873.             }
  874.             else if (m_pbReadBuffer == NULL)
  875.             {
  876.                 m_pbReadBuffer = new BYTE[nReadSize];
  877.                 m_nReadBufferPos = nReadSize;
  878.             }
  879.             else
  880.             {
  881.                 DWORD dwMoved = m_nReadBufferSize - m_nReadBufferPos;
  882.                 LPBYTE pbTemp = m_pbReadBuffer;
  883.                 m_pbReadBuffer = new BYTE[nReadSize];
  884.  
  885.                 if (dwMoved > 0)
  886.                 {
  887.                     memcpy(m_pbReadBuffer, pbTemp + m_nReadBufferPos, dwMoved);
  888.                     m_nReadBufferPos = 0;
  889.                     m_nReadBufferBytes = dwMoved;
  890.                 }
  891.                 else
  892.                 {
  893.                     m_nReadBufferBytes = 0;
  894.                     m_nReadBufferPos = nReadSize;
  895.                 }
  896.                 delete [] pbTemp;
  897.             }
  898.  
  899.             m_nReadBufferSize = nReadSize;
  900.         }
  901.     }
  902.  
  903.     return bRet;
  904. }
  905.  
  906. #if !defined(_WIN32_WCE)
  907. BOOL CInternetFile::SetWriteBufferSize(UINT nWriteSize)
  908. {
  909.     ASSERT_VALID(this);
  910.     BOOL bRet = TRUE;
  911.  
  912.     if (nWriteSize != m_nWriteBufferSize)
  913.     {
  914.         if (m_nWriteBufferPos > nWriteSize)
  915.             Flush();
  916.  
  917.         if (nWriteSize == 0)
  918.         {
  919.             delete [] m_pbWriteBuffer;
  920.             m_pbWriteBuffer = NULL;
  921.         }
  922.         else if (m_pbWriteBuffer == NULL)
  923.         {
  924.             m_pbWriteBuffer = new BYTE[nWriteSize];
  925.             m_nWriteBufferPos = 0;
  926.         }
  927.         else
  928.         {
  929.             LPBYTE pbTemp = m_pbWriteBuffer;
  930.             m_pbWriteBuffer = new BYTE[nWriteSize];
  931.  
  932.             memcpy(m_pbWriteBuffer, pbTemp, m_nWriteBufferPos);
  933.             delete [] pbTemp;
  934.         }
  935.  
  936.         m_nWriteBufferSize = nWriteSize;
  937.     }
  938.  
  939.     return bRet;
  940. }
  941.  
  942. LONG CInternetFile::Seek(LONG lOffset, UINT nFrom)
  943. {
  944.     ASSERT_VALID(this);
  945.     ASSERT(m_hFile != NULL);
  946.     ASSERT(m_bReadMode);
  947.     ASSERT(m_pbReadBuffer == NULL);
  948.  
  949.     // can't do this on a file for writing
  950.     // can't do this on a file that's got a buffer
  951.  
  952.     if (!m_bReadMode || m_pbReadBuffer != NULL)
  953.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  954.  
  955.     switch (nFrom)
  956.     {
  957.         case begin:
  958.             nFrom = FILE_BEGIN;
  959.             break;
  960.  
  961.         case current:
  962.             nFrom = FILE_CURRENT;
  963.             break;
  964.  
  965.         case end:
  966.             nFrom = FILE_END;
  967.             break;
  968.  
  969.         default:
  970.             ASSERT(FALSE);  // got a bogus nFrom value
  971.             AfxThrowInternetException(m_dwContext, ERROR_INVALID_PARAMETER);
  972.             break;
  973.     }
  974.  
  975.     LONG lRet;
  976.     lRet = InternetSetFilePointer(m_hFile, lOffset, NULL, nFrom, m_dwContext);
  977.     if (lRet == -1)
  978.         AfxThrowInternetException(m_dwContext);
  979.  
  980.     return lRet;
  981. }
  982. #endif // _WIN32_WCE
  983.  
  984. CInternetFile::~CInternetFile()
  985. {
  986.     if (m_hFile != NULL)
  987.     {
  988. #ifdef _DEBUG
  989.         USES_CONVERSION;
  990.         LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  991.         TRACE2("Warning: destroying an open %s with handle %8.8X\n",
  992.             pszName, m_hFile);
  993. #endif
  994.         Close();
  995.     }
  996.  
  997.     if (m_pbReadBuffer != NULL)
  998.         delete m_pbReadBuffer;
  999.  
  1000.     if (m_pbWriteBuffer != NULL)
  1001.         delete m_pbWriteBuffer;
  1002. }
  1003.  
  1004. void CInternetFile::Abort()
  1005. {
  1006.     ASSERT_VALID(this);
  1007.     if (m_hFile != NULL)
  1008.         Close();
  1009.     m_strFileName.Empty();
  1010. }
  1011.  
  1012. #if !defined(_WIN32_WCE)
  1013. void CInternetFile::Flush()
  1014. {
  1015.     if (m_pbWriteBuffer != NULL && m_nWriteBufferPos > 0)
  1016.     {
  1017.         DWORD dwBytes;
  1018.  
  1019.         if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  1020.                 m_nWriteBufferPos, &dwBytes))
  1021.             AfxThrowInternetException(m_dwContext);
  1022.  
  1023.         if (dwBytes != m_nWriteBufferPos)
  1024.             AfxThrowInternetException(m_dwContext);
  1025.  
  1026.         m_nWriteBufferPos = 0;
  1027.     }
  1028. }
  1029. #endif // _WIN32_WCE
  1030.  
  1031. void CInternetFile::Close()
  1032. {
  1033.     if (m_hFile != NULL)
  1034.     {
  1035.         Flush();
  1036.         InternetCloseHandle(m_hFile);
  1037.         _afxSessionMap.RemoveKey(m_hFile);
  1038.         m_hFile = NULL;
  1039.  
  1040.         if (m_pbWriteBuffer != NULL)
  1041.         {
  1042.             delete [] m_pbWriteBuffer;
  1043.             m_pbWriteBuffer = NULL;
  1044.         }
  1045.  
  1046.         if (m_pbReadBuffer != NULL)
  1047.         {
  1048.             delete [] m_pbReadBuffer;
  1049.             m_pbReadBuffer = NULL;
  1050.         }
  1051.     }
  1052. }
  1053.  
  1054. UINT CInternetFile::Read(LPVOID lpBuf, UINT nCount)
  1055. {
  1056.     ASSERT_VALID(this);
  1057.     ASSERT(AfxIsValidAddress(lpBuf, nCount));
  1058.     ASSERT(m_hFile != NULL);
  1059.     ASSERT(m_bReadMode);
  1060.  
  1061.     DWORD dwBytes;
  1062.  
  1063.     if (!m_bReadMode || m_hFile == NULL)
  1064.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1065.  
  1066.     if (m_pbReadBuffer == NULL)
  1067.     {
  1068.         if (!InternetReadFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  1069.                 AfxThrowInternetException(m_dwContext);
  1070.         return dwBytes;
  1071.     }
  1072.  
  1073.     LPBYTE lpbBuf = (LPBYTE) lpBuf;
  1074.  
  1075.     // if the requested size is bigger than our buffer,
  1076.     // then handle it directly
  1077.  
  1078.     if (nCount >= m_nReadBufferSize)
  1079.     {
  1080.         DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  1081.         memcpy(lpBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  1082.         m_nReadBufferPos = m_nReadBufferSize;
  1083.         if (!InternetReadFile(m_hFile, lpbBuf+dwMoved, nCount-dwMoved, &dwBytes))
  1084.                 AfxThrowInternetException(m_dwContext);
  1085.         dwBytes += dwMoved;
  1086.     }
  1087.     else
  1088.     {
  1089.         if (m_nReadBufferPos + nCount >= m_nReadBufferBytes)
  1090.         {
  1091.             DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  1092.             memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  1093.  
  1094.             DWORD dwRead;
  1095.             if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1096.                     &dwRead))
  1097.                 AfxThrowInternetException(m_dwContext);
  1098.             m_nReadBufferBytes = dwRead;
  1099.  
  1100.             dwRead = min(nCount - dwMoved, m_nReadBufferBytes);
  1101.             memcpy(lpbBuf + dwMoved, m_pbReadBuffer, dwRead);
  1102.             m_nReadBufferPos = dwRead;
  1103.             dwBytes = dwMoved + dwRead;
  1104.         }
  1105.         else
  1106.         {
  1107.             memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, nCount);
  1108.             m_nReadBufferPos += nCount;
  1109.             dwBytes = nCount;
  1110.         }
  1111.     }
  1112.  
  1113.     return dwBytes;
  1114. }
  1115.  
  1116. #if !defined(_WIN32_WCE)
  1117. void CInternetFile::Write(const void* lpBuf, UINT nCount)
  1118. {
  1119.     ASSERT_VALID(this);
  1120.     ASSERT(m_hFile != NULL);
  1121.     ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  1122.     ASSERT(m_bReadMode == FALSE || m_bReadMode == -1);
  1123.  
  1124.     if (m_bReadMode == TRUE || m_hFile == NULL)
  1125.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1126.  
  1127.     DWORD dwBytes;
  1128.     if (m_pbWriteBuffer == NULL)
  1129.     {
  1130.         if (!InternetWriteFile(m_hFile, lpBuf, nCount, &dwBytes))
  1131.             AfxThrowInternetException(m_dwContext);
  1132.  
  1133.         if (dwBytes != nCount)
  1134.             AfxThrowInternetException(m_dwContext);
  1135.     }
  1136.     else
  1137.     {
  1138.         if ((m_nWriteBufferPos + nCount) >= m_nWriteBufferSize)
  1139.         {
  1140.             // write what is in the buffer just now
  1141.  
  1142.             if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  1143.                     m_nWriteBufferPos, &dwBytes))
  1144.                 AfxThrowInternetException(m_dwContext);
  1145.  
  1146.             // reset the buffer position since it is now clean
  1147.  
  1148.             m_nWriteBufferPos = 0;
  1149.         }
  1150.  
  1151.         // if we can't hope to buffer the write request,
  1152.         // do it immediately ... otherwise, buffer it!
  1153.  
  1154.         if (nCount >= m_nWriteBufferSize)
  1155.         {
  1156.             if (!InternetWriteFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  1157.                 AfxThrowInternetException(m_dwContext);
  1158.         }
  1159.         else
  1160.         {
  1161.             memcpy(m_nWriteBufferPos + m_pbWriteBuffer, lpBuf, nCount);
  1162.             m_nWriteBufferPos += nCount;
  1163.         }
  1164.     }
  1165. }
  1166.  
  1167. void CInternetFile::WriteString(LPCTSTR pstr)
  1168. {
  1169.     ASSERT(m_bReadMode == TRUE || m_bReadMode == -1);
  1170.     ASSERT(AfxIsValidString(pstr));
  1171.     ASSERT_VALID(this);
  1172.     ASSERT(m_hFile != NULL);
  1173.  
  1174.     if (m_bReadMode == TRUE)
  1175.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1176.  
  1177.     Write(pstr, lstrlen(pstr));
  1178. }
  1179. #endif // _WIN32_WCE
  1180.  
  1181. LPTSTR CInternetFile::ReadString(LPTSTR pstr, UINT nMax)
  1182. {
  1183.     ASSERT_VALID(this);
  1184.     ASSERT(m_hFile != NULL);
  1185.     ASSERT(AfxIsValidAddress(pstr, nMax*sizeof(TCHAR)));
  1186.     DWORD dwRead;
  1187.  
  1188.     // if we're reading line-by-line, we must have a buffer
  1189.  
  1190.     if (m_pbReadBuffer == NULL)
  1191.     {
  1192.         if (!SetReadBufferSize(4096))   // arbitrary but reasonable
  1193.             return NULL;
  1194.         if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1195.                 &dwRead))
  1196.             AfxThrowInternetException(m_dwContext);
  1197.         m_nReadBufferBytes = dwRead;
  1198.         m_nReadBufferPos = 0;
  1199.     }
  1200.  
  1201.     LPTSTR pstrChar = (LPTSTR) (m_pbReadBuffer + m_nReadBufferPos);
  1202.     LPTSTR pstrTarget = pstr;
  1203.  
  1204.     while (--nMax)
  1205.     {
  1206.         if (m_nReadBufferPos >= m_nReadBufferBytes)
  1207.         {
  1208.             if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  1209.                     &dwRead))
  1210.                 AfxThrowInternetException(m_dwContext);
  1211.             m_nReadBufferBytes = dwRead;
  1212.             if (m_nReadBufferBytes == 0)
  1213.             {
  1214.                 *pstrTarget = '\0';
  1215.                 if (pstrTarget == pstr)
  1216.                     return NULL;
  1217.                 else
  1218.                     return pstr;
  1219.             }
  1220.             else
  1221.             {
  1222.                 m_nReadBufferPos = 0;
  1223.                 pstrChar = (LPTSTR) m_pbReadBuffer;
  1224.             }
  1225.         }
  1226.  
  1227.         if (*pstrChar != '\r')
  1228.             *pstrTarget++ = *pstrChar;
  1229.  
  1230. #if defined(_WIN32_WCE)
  1231.         m_nReadBufferPos += 2; // WinCE: for UNICODE characters
  1232. #else // _WIN32_WCE
  1233.         m_nReadBufferPos++;
  1234. #endif // _WIN32_WCE
  1235.         if (*pstrChar++ == '\n')
  1236.             break;
  1237.     }
  1238.  
  1239.     *pstrTarget = '\0';
  1240.     return pstr;
  1241. }
  1242.  
  1243. BOOL CInternetFile::ReadString(CString& rString)
  1244. {
  1245.     ASSERT_VALID(this);
  1246.     ASSERT(m_hFile != NULL);
  1247.  
  1248.     rString = _T("");    // empty string without deallocating
  1249.     const int nMaxSize = 128;
  1250.  
  1251.     LPTSTR pstrPlace = rString.GetBuffer(nMaxSize);
  1252.     LPTSTR pstrResult;
  1253.     int nLen;
  1254.  
  1255.     do
  1256.     {
  1257.         pstrResult = ReadString(pstrPlace, nMaxSize);
  1258.         rString.ReleaseBuffer();
  1259.  
  1260.         // if string is read completely or EOF
  1261.         if (pstrResult == NULL ||
  1262.             (nLen = lstrlen(pstrPlace)) < (nMaxSize-1) ||
  1263.             pstrPlace[nLen-1] == '\n')
  1264.             break;
  1265.  
  1266.         nLen = rString.GetLength();
  1267.         pstrPlace = rString.GetBuffer(nMaxSize + nLen) + nLen;
  1268.     } while (1);
  1269.  
  1270.     // remove '\n' from end of string if present
  1271.     pstrPlace = rString.GetBuffer(0);
  1272.     nLen = rString.GetLength();
  1273.     if (nLen != 0 && pstrPlace[nLen-1] == '\n')
  1274.         pstrPlace[nLen-1] = '\0';
  1275.     rString.ReleaseBuffer();
  1276.  
  1277.     return (pstrResult != NULL);
  1278. }
  1279.  
  1280. DWORD CInternetFile::GetLength() const
  1281. {
  1282.     ASSERT_VALID(this);
  1283.     ASSERT(m_hFile != NULL);
  1284.  
  1285.     DWORD dwRet = 0;
  1286.  
  1287.     if (m_hFile != NULL)
  1288.     {
  1289.         if (!InternetQueryDataAvailable(m_hFile, &dwRet, 0, 0))
  1290.             dwRet = 0;
  1291.     }
  1292.  
  1293.     return dwRet;
  1294. }
  1295.  
  1296. void CInternetFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1297. {
  1298.     ASSERT_VALID(this);
  1299.     ASSERT(m_hFile != NULL);
  1300.  
  1301.     AfxThrowNotSupportedException();
  1302. }
  1303.  
  1304. void CInternetFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1305. {
  1306.     ASSERT_VALID(this);
  1307.     ASSERT(m_hFile != NULL);
  1308.  
  1309.     AfxThrowNotSupportedException();
  1310. }
  1311.  
  1312. void CInternetFile::SetLength(DWORD)
  1313. {
  1314.     ASSERT_VALID(this);
  1315.     ASSERT(m_hFile != NULL);
  1316.  
  1317.     AfxThrowNotSupportedException();
  1318. }
  1319.  
  1320. CFile* CInternetFile::Duplicate() const
  1321. {
  1322.     ASSERT_VALID(this);
  1323. #if !defined(_WIN32_WCE)
  1324.     ASSERT(m_pStream != NULL);
  1325. #endif // _WIN32_WCE
  1326.  
  1327.     AfxThrowNotSupportedException();
  1328.     return NULL;
  1329. }
  1330.  
  1331. #ifdef _DEBUG
  1332. void CInternetFile::AssertValid() const
  1333. {
  1334.     // Don't call CStdioFile's AsssertValid()
  1335.     CFile::AssertValid();
  1336.  
  1337. #if !defined(_WIN32_WCE)
  1338.     ASSERT(m_hConnection != NULL);
  1339. #endif // _WIN32_WCE
  1340.  
  1341.     // make sure we really have a decent handle
  1342.     if (m_hFile != NULL)
  1343.     {
  1344.         DWORD dwResult = AfxGetInternetHandleType(m_hFile);
  1345.  
  1346.         if (IsKindOf(RUNTIME_CLASS(CHttpFile)))
  1347.         {
  1348.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1349.         }
  1350. #if !defined(_WIN32_WCE)
  1351.         else if (IsKindOf(RUNTIME_CLASS(CGopherFile)))
  1352.         {
  1353.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE ||
  1354.                 dwResult == INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML ||
  1355.                 dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML ||
  1356.                 dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1357.         }
  1358. #endif // _WIN32_WCE
  1359.         else if (IsKindOf(RUNTIME_CLASS(CInternetFile)))
  1360.         {
  1361.             ASSERT(dwResult == INTERNET_HANDLE_TYPE_FTP_FILE ||
  1362.                 dwResult == INTERNET_HANDLE_TYPE_FTP_FILE_HTML ||
  1363.                 dwResult == INTERNET_HANDLE_TYPE_FTP_FIND_HTML ||
  1364.                 dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1365.         }
  1366.         else
  1367.             ASSERT(FALSE);  // some bogus object!
  1368.     }
  1369. }
  1370.  
  1371. void CInternetFile::Dump(CDumpContext& dc) const
  1372. {
  1373.     CObject::Dump(dc);
  1374.  
  1375.     dc << "\na " << GetRuntimeClass()->m_lpszClassName;
  1376.     dc << " with handle " << (UINT)m_hFile;
  1377. }
  1378. #endif
  1379.  
  1380. /////////////////////////////////////////////////////////////////////////////
  1381. // CInternetConnection
  1382.  
  1383. CInternetConnection::CInternetConnection(CInternetSession* pSession,
  1384.     LPCTSTR pstrServerName,
  1385.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1386.     DWORD dwContext /* = 1 */)
  1387.     : m_strServerName(pstrServerName)
  1388. {
  1389.     ASSERT(pSession != NULL);
  1390.     ASSERT_VALID(pSession);
  1391.     ASSERT(pstrServerName != NULL);
  1392.  
  1393.     m_nPort = nPort;
  1394.     m_pSession = pSession;
  1395.     m_hConnection = NULL;
  1396.     if (dwContext == 1)
  1397.         dwContext = pSession->GetContext();
  1398.     m_dwContext = dwContext;
  1399. }
  1400.  
  1401. CInternetConnection::~CInternetConnection()
  1402. {
  1403.     if (m_hConnection != NULL)
  1404.     {
  1405. #ifdef _DEBUG
  1406.         USES_CONVERSION;
  1407.         LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  1408.         TRACE3("Warning: Disconnecting %s handle %8.8X in context %8.8X at destruction.\n",
  1409.             pszName, m_hConnection, m_dwContext);
  1410. #endif
  1411.         Close();
  1412.     }
  1413. }
  1414.  
  1415. BOOL CInternetConnection::SetOption(DWORD dwOption, LPVOID lpBuffer,
  1416.     DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  1417. {
  1418.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1419.         dwOption <= INTERNET_LAST_OPTION);
  1420.     ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  1421.     ASSERT(dwBufferLength != 0);
  1422.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1423.  
  1424.     // bogus flag?
  1425.     ASSERT(dwFlags == 0 || WCE_IF(FALSE, ((dwFlags & ISO_VALID_FLAGS) == dwFlags)));
  1426.  
  1427.     return WCE_FCTN(InternetSetOptionEx)(m_hConnection, dwOption,
  1428.         lpBuffer, dwBufferLength, dwFlags);
  1429. }
  1430.  
  1431. BOOL CInternetConnection::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  1432.     LPDWORD lpdwBufferLength) const
  1433. {
  1434.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1435.         dwOption <= INTERNET_LAST_OPTION);
  1436.     ASSERT_POINTER(lpdwBufferLength, DWORD);
  1437.     ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  1438.     ASSERT(*lpdwBufferLength != 0);
  1439.  
  1440.     return InternetQueryOption(m_hConnection, dwOption,
  1441.         lpBuffer, lpdwBufferLength);
  1442. }
  1443.  
  1444. BOOL CInternetConnection::QueryOption(DWORD dwOption, DWORD& dwValue) const
  1445. {
  1446.     DWORD dwLen = sizeof(DWORD);
  1447.     return InternetQueryOption(m_hConnection, dwOption,
  1448.         &dwValue, &dwLen);
  1449. }
  1450.  
  1451. BOOL CInternetConnection::QueryOption(DWORD dwOption, CString& refString) const
  1452. {
  1453.     ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1454.         dwOption <= INTERNET_LAST_OPTION);
  1455.  
  1456.     return _AfxQueryCStringInternetOption(m_hConnection, dwOption, refString);
  1457. }
  1458.  
  1459. void CInternetConnection::Close()
  1460. {
  1461.     if (m_hConnection != NULL)
  1462.     {
  1463.         InternetCloseHandle(m_hConnection);
  1464.         _afxSessionMap.RemoveKey(m_hConnection);
  1465.         m_hConnection = NULL;
  1466.     }
  1467. }
  1468.  
  1469. #ifdef _DEBUG
  1470. void CInternetConnection::Dump(CDumpContext& dc) const
  1471. {
  1472.     CObject::Dump(dc);
  1473.     dc << "m_hConnection = " << m_hConnection;
  1474. }
  1475.  
  1476. void CInternetConnection::AssertValid() const
  1477. {
  1478.     CObject::AssertValid();
  1479. }
  1480. #endif
  1481.  
  1482.  
  1483. #if !defined(_WIN32_WCE_NO_FTP)
  1484. /////////////////////////////////////////////////////////////////////////////
  1485. // CFtpConnection
  1486.  
  1487. CFtpConnection::~CFtpConnection()
  1488. {
  1489. }
  1490.  
  1491. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1492.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1493.     : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER,
  1494.     dwContext)
  1495. {
  1496.     ASSERT(pSession != NULL);
  1497.     ASSERT(AfxIsValidString(pstrServer));
  1498.  
  1499.     BOOL bBadType = FALSE;
  1500.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_FTP)
  1501.     {
  1502.         ASSERT(FALSE);      // used the wrong handle type
  1503.         bBadType = TRUE;
  1504.     }
  1505.  
  1506.     m_strServerName = pstrServer;
  1507.     m_hConnection = hConnected;
  1508.     if (m_hConnection == NULL || bBadType)
  1509.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1510.     else
  1511.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1512. }
  1513.  
  1514. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1515.     LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1516.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1517.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1518.     BOOL bPassive /* = FALSE */)
  1519.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1520. {
  1521.     ASSERT(pSession != NULL);
  1522.     ASSERT_KINDOF(CInternetSession, pSession);
  1523.     ASSERT(AfxIsValidString(pstrServer));
  1524.  
  1525.     m_strServerName = pstrServer;
  1526.  
  1527.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1528.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_FTP,
  1529.         (bPassive ? INTERNET_FLAG_PASSIVE : 0), m_dwContext);
  1530.  
  1531.     if (m_hConnection == NULL)
  1532.         AfxThrowInternetException(m_dwContext, ::GetLastError());
  1533.     else
  1534.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1535. }
  1536.  
  1537. void CFtpConnection::Close()
  1538. {
  1539.     CInternetConnection::Close();
  1540. }
  1541.  
  1542. BOOL CFtpConnection::Remove(LPCTSTR pstrFileName)
  1543. {
  1544.     ASSERT_VALID(this);
  1545.     ASSERT(m_hConnection != NULL);
  1546.     ASSERT(AfxIsValidString(pstrFileName));
  1547.  
  1548.     return FtpDeleteFile(m_hConnection, pstrFileName);
  1549. }
  1550.  
  1551. BOOL CFtpConnection::Rename(LPCTSTR pstrExisting, LPCTSTR pstrNew)
  1552. {
  1553.     ASSERT_VALID(this);
  1554.     ASSERT(m_hConnection != NULL);
  1555.     ASSERT(AfxIsValidString(pstrExisting));
  1556.     ASSERT(AfxIsValidString(pstrNew));
  1557.  
  1558.     return FtpRenameFile(m_hConnection, pstrExisting, pstrNew);
  1559. }
  1560.  
  1561. BOOL CFtpConnection::CreateDirectory(LPCTSTR pstrDirName)
  1562. {
  1563.     ASSERT_VALID(this);
  1564.     ASSERT(m_hConnection != NULL);
  1565.     ASSERT(AfxIsValidString(pstrDirName));
  1566.  
  1567.     return FtpCreateDirectory(m_hConnection, pstrDirName);
  1568. }
  1569.  
  1570. BOOL CFtpConnection::RemoveDirectory(LPCTSTR pstrDirName)
  1571. {
  1572.     ASSERT_VALID(this);
  1573.     ASSERT(m_hConnection != NULL);
  1574.     ASSERT(AfxIsValidString(pstrDirName));
  1575.  
  1576.     return FtpRemoveDirectory(m_hConnection, pstrDirName);
  1577. }
  1578.  
  1579. BOOL CFtpConnection::SetCurrentDirectory(LPCTSTR pstrDirName)
  1580. {
  1581.     ASSERT_VALID(this);
  1582.     ASSERT(m_hConnection != NULL);
  1583.     ASSERT(AfxIsValidString(pstrDirName));
  1584.  
  1585.     return FtpSetCurrentDirectory(m_hConnection, pstrDirName);
  1586. }
  1587.  
  1588. BOOL CFtpConnection::GetCurrentDirectory(LPTSTR pstrDirName,
  1589.     LPDWORD lpdwLen) const
  1590. {
  1591.     ASSERT_VALID(this);
  1592.     ASSERT(m_hConnection != NULL);
  1593.     ASSERT(AfxIsValidAddress(pstrDirName, *lpdwLen));
  1594.     ASSERT(lpdwLen != 0);
  1595.  
  1596.     return FtpGetCurrentDirectory(m_hConnection, pstrDirName, lpdwLen);
  1597. }
  1598.  
  1599. BOOL CFtpConnection::GetCurrentDirectoryAsURL(CString& strDirName) const
  1600. {
  1601.     CString strDirectory;
  1602.     if (!GetCurrentDirectory(strDirectory))
  1603.         return FALSE;
  1604.  
  1605.     strDirName = _afxURLftp;
  1606.     strDirName += GetServerName();
  1607.  
  1608.     if (strDirectory[0] != '/')
  1609.         strDirName += '/';
  1610.  
  1611.     strDirName += strDirectory;
  1612.     return TRUE;
  1613. }
  1614.  
  1615. BOOL CFtpConnection::GetCurrentDirectoryAsURL(LPTSTR pstrName,
  1616.     LPDWORD lpdwLen) const
  1617. {
  1618.     ASSERT(lpdwLen != NULL);
  1619.     ASSERT_POINTER(lpdwLen, DWORD);
  1620.     ASSERT(AfxIsValidAddress(pstrName, *lpdwLen));
  1621.     ASSERT(*lpdwLen != 0);
  1622.  
  1623.     CString strTemp;
  1624.  
  1625.     if (lpdwLen == NULL || !GetCurrentDirectoryAsURL(strTemp))
  1626.         return FALSE;
  1627.  
  1628.     if (pstrName == NULL)
  1629.         *lpdwLen = strTemp.GetLength();
  1630.     else
  1631.         lstrcpyn(pstrName, (LPCTSTR) strTemp, max(0, *lpdwLen -1));
  1632.  
  1633.     return TRUE;
  1634. }
  1635.  
  1636. BOOL CFtpConnection::GetCurrentDirectory(CString& strDirName) const
  1637. {
  1638.     ASSERT_VALID(this);
  1639.     ASSERT(m_hConnection != NULL);
  1640.  
  1641.     DWORD dwLen = INTERNET_MAX_PATH_LENGTH;
  1642.     LPTSTR pstrTarget = strDirName.GetBufferSetLength(dwLen);
  1643.     BOOL bRet = FtpGetCurrentDirectory(m_hConnection, pstrTarget, &dwLen);
  1644.  
  1645.     if (bRet)
  1646.         strDirName.ReleaseBuffer(dwLen);
  1647.     else
  1648.         strDirName.ReleaseBuffer(0);
  1649.  
  1650.     return bRet;
  1651. }
  1652.  
  1653. CInternetFile* CFtpConnection::OpenFile(LPCTSTR pstrFileName,
  1654.     DWORD dwAccess /* = GENERIC_READ */,
  1655.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1656.     DWORD dwContext /* = 1 */)
  1657. {
  1658.     ASSERT_VALID(this);
  1659.     ASSERT(m_hConnection != NULL);
  1660.     ASSERT(dwAccess != (GENERIC_READ | GENERIC_WRITE));
  1661.     ASSERT(dwAccess == GENERIC_READ || dwAccess == GENERIC_WRITE);
  1662.     ASSERT(AfxIsValidString(pstrFileName));
  1663.  
  1664.     HINTERNET hFile;
  1665.     if (dwContext == 1)
  1666.         dwContext = m_dwContext;
  1667.  
  1668.     hFile = FtpOpenFile(m_hConnection, pstrFileName, dwAccess,
  1669.         dwFlags, dwContext);
  1670.     if (hFile == NULL)
  1671.         AfxThrowInternetException(dwContext);
  1672.  
  1673.     CInternetFile* pFile = new CInternetFile(hFile, pstrFileName, this,
  1674.         (dwAccess == GENERIC_READ));
  1675.     return pFile;
  1676. }
  1677.  
  1678. BOOL CFtpConnection::PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile,
  1679.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1680.     DWORD dwContext /* = 1 */)
  1681. {
  1682.     ASSERT_VALID(this);
  1683.     ASSERT(m_hConnection != NULL);
  1684.     ASSERT(AfxIsValidString(pstrRemoteFile));
  1685.     ASSERT(AfxIsValidString(pstrLocalFile));
  1686.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1687.  
  1688.     if (dwContext == 1)
  1689.         dwContext = m_dwContext;
  1690.  
  1691.     return FtpPutFile(m_hConnection, pstrLocalFile, pstrRemoteFile,
  1692.         dwFlags, dwContext);
  1693. }
  1694.  
  1695. BOOL CFtpConnection::GetFile(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile,
  1696.     BOOL bFailIfExists /* = TRUE */,
  1697.     DWORD dwAttributes /* = FILE_ATTRIBUTE_NORMAL */,
  1698.     DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */, DWORD dwContext /* = 1 */)
  1699. {
  1700.     ASSERT_VALID(this);
  1701.     ASSERT(m_hConnection != NULL);
  1702.     ASSERT(AfxIsValidString(pstrRemoteFile));
  1703.     ASSERT(AfxIsValidString(pstrLocalFile));
  1704.     ASSERT(!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY));
  1705.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1706.  
  1707.     if (dwContext == 1)
  1708.         dwContext = m_dwContext;
  1709.  
  1710.     return FtpGetFile(m_hConnection, pstrRemoteFile, pstrLocalFile,
  1711.         bFailIfExists, dwAttributes, dwFlags, dwContext);
  1712. }
  1713.  
  1714. #ifdef _DEBUG
  1715. void CFtpConnection::Dump(CDumpContext& dc) const
  1716. {
  1717.     CInternetConnection::Dump(dc);
  1718.     dc << "\nm_strServerName = " << m_strServerName;
  1719. }
  1720.  
  1721. void CFtpConnection::AssertValid() const
  1722. {
  1723.     ASSERT(m_pSession != NULL);
  1724.     if (m_hConnection != NULL)
  1725.     {
  1726.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  1727.                 == INTERNET_HANDLE_TYPE_CONNECT_FTP);
  1728.     }
  1729. }
  1730. #endif
  1731.  
  1732.  
  1733. #endif // _WIN32_WCE_NO_FTP
  1734. #if !defined(_WIN32_WCE)
  1735. /////////////////////////////////////////////////////////////////////////////
  1736. // CGopherConnection
  1737.  
  1738. CGopherConnection::~CGopherConnection()
  1739. {
  1740. }
  1741.  
  1742. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1743.     LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1744.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1745.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1746.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1747. {
  1748.     ASSERT(pSession != NULL);
  1749.     ASSERT_KINDOF(CInternetSession, pSession);
  1750.     ASSERT(AfxIsValidString(pstrServer));
  1751.  
  1752.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1753.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_GOPHER,
  1754.         0, m_dwContext);
  1755.  
  1756.     if (m_hConnection == NULL)
  1757.         AfxThrowInternetException(m_dwContext);
  1758.     else
  1759.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1760. }
  1761.  
  1762. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1763.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1764.     : CInternetConnection(pSession, pstrServer,
  1765.         INTERNET_INVALID_PORT_NUMBER, dwContext)
  1766. {
  1767.     ASSERT(pSession != NULL);
  1768.     ASSERT(AfxIsValidString(pstrServer));
  1769.  
  1770.     BOOL bBadType = FALSE;
  1771.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_GOPHER)
  1772.     {
  1773.         ASSERT(FALSE);      // used the wrong handle type
  1774.         bBadType = TRUE;
  1775.     }
  1776.  
  1777.     m_hConnection = hConnected;
  1778.     if (m_hConnection == NULL || bBadType)
  1779.         AfxThrowInternetException(m_dwContext);
  1780.     else
  1781.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1782. }
  1783.  
  1784. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrLocator)
  1785. {
  1786.     CGopherLocator ret(pstrLocator, lstrlen(pstrLocator));
  1787.     return ret;
  1788. }
  1789.  
  1790. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrServerName,
  1791.     LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType,
  1792.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1793. {
  1794.     TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1795.     DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1796.     ASSERT(AfxIsValidString(pstrDisplayString));
  1797.     ASSERT(AfxIsValidString(pstrServerName));
  1798.     ASSERT(AfxIsValidString(pstrSelectorString));
  1799.  
  1800.     if (!GopherCreateLocator(pstrServerName, nPort,
  1801.             pstrDisplayString, pstrSelectorString, dwGopherType,
  1802.             szLocator, &dwLocLen))
  1803.         AfxThrowInternetException(0);
  1804.  
  1805.     CGopherLocator ret(szLocator, dwLocLen);
  1806.     return ret;
  1807. }
  1808.  
  1809. CGopherLocator CGopherConnection::CreateLocator(
  1810.     LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType)
  1811. {
  1812.     TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1813.     DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1814.     ASSERT(AfxIsValidString(pstrDisplayString));
  1815.     ASSERT(AfxIsValidString(pstrSelectorString));
  1816.  
  1817.     if (!GopherCreateLocator(m_strServerName, m_nPort,
  1818.             pstrDisplayString, pstrSelectorString, dwGopherType,
  1819.             szLocator, &dwLocLen))
  1820.         AfxThrowInternetException(m_dwContext);
  1821.  
  1822.     CGopherLocator ret(szLocator, dwLocLen);
  1823.     return ret;
  1824. }
  1825.  
  1826.  
  1827. BOOL CGopherConnection::GetAttribute(CGopherLocator& refLocator,
  1828.     CString strRequestedAttributes, CString& strResult)
  1829. {
  1830.     DWORD dwLen = 4*MIN_GOPHER_ATTRIBUTE_LENGTH; // more than the minimum
  1831.     BOOL bRet;
  1832.     LPTSTR pstrResult = strResult.GetBuffer(dwLen);
  1833.  
  1834.     if (!GopherGetAttribute(m_hConnection, (LPCTSTR) refLocator,
  1835.             pstrResult, NULL, dwLen, &dwLen,
  1836.             NULL, m_dwContext))
  1837.     {
  1838.         bRet = FALSE;
  1839.         strResult.ReleaseBuffer(0);
  1840.     }
  1841.     else
  1842.     {
  1843.         bRet = TRUE;
  1844.         strResult.ReleaseBuffer(dwLen);
  1845.     }
  1846.  
  1847.     return bRet;
  1848. }
  1849.  
  1850. CGopherFile* CGopherConnection::OpenFile(CGopherLocator& refLocator,
  1851.     DWORD dwFlags /* = 0 */, LPCTSTR pstrView /* = NULL */,
  1852.     DWORD dwContext /* = 1 */)
  1853. {
  1854.     ASSERT_VALID(this);
  1855.     ASSERT(m_hConnection != NULL);
  1856.  
  1857.     HINTERNET hFile;
  1858.     if (dwContext == 1)
  1859.         dwContext = m_dwContext;
  1860.  
  1861.     hFile = GopherOpenFile(m_hConnection, (LPCTSTR) refLocator, pstrView,
  1862.         dwFlags, dwContext);
  1863.  
  1864.     if (hFile == NULL)
  1865.         AfxThrowInternetException(dwContext);
  1866.  
  1867.     CGopherFile* pFile = new CGopherFile(hFile, refLocator, this);
  1868.     return pFile;
  1869. }
  1870.  
  1871. void CGopherConnection::Close()
  1872. {
  1873.     CInternetConnection::Close();
  1874. }
  1875.  
  1876. #ifdef _DEBUG
  1877. void CGopherConnection::Dump(CDumpContext& dc) const
  1878. {
  1879.     CInternetConnection::Dump(dc);
  1880.     dc << "\nm_strServerName = " << m_strServerName;
  1881. }
  1882.  
  1883. void CGopherConnection::AssertValid() const
  1884. {
  1885.     ASSERT(m_pSession != NULL);
  1886.     if (m_hConnection != NULL)
  1887.     {
  1888.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  1889.                 == INTERNET_HANDLE_TYPE_CONNECT_GOPHER);
  1890.     }
  1891. }
  1892. #endif
  1893. #endif // _WIN32_WCE
  1894.  
  1895.  
  1896. /////////////////////////////////////////////////////////////////////////////
  1897. // CHttpConnection
  1898.  
  1899. CHttpConnection::~CHttpConnection()
  1900. {
  1901. }
  1902.  
  1903. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1904.     HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext /* = 0 */)
  1905.     : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER, dwContext)
  1906. {
  1907.     ASSERT(pSession != NULL);
  1908.     ASSERT(AfxIsValidString(pstrServer));
  1909.  
  1910.     BOOL bBadType = FALSE;
  1911.     if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_HTTP)
  1912.     {
  1913.         ASSERT(FALSE);      // used the wrong handle type
  1914.         bBadType = TRUE;
  1915.     }
  1916.  
  1917.     m_hConnection = hConnected;
  1918.     if (m_hConnection == NULL || bBadType)
  1919.         AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1920.     else
  1921.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1922. }
  1923.  
  1924. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1925.     LPCTSTR pstrServer,
  1926.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1927.     LPCTSTR pstrUserName /* = NULL */,
  1928.     LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 1 */)
  1929.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1930. {
  1931.     ASSERT(pSession != NULL);
  1932.     ASSERT_KINDOF(CInternetSession, pSession);
  1933.     ASSERT(AfxIsValidString(pstrServer));
  1934.  
  1935.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1936.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1937.         0, m_dwContext);
  1938.  
  1939.     if (m_hConnection == NULL)
  1940.         AfxThrowInternetException(m_dwContext);
  1941.     else
  1942.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1943. }
  1944.  
  1945. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1946.     LPCTSTR pstrServer, DWORD dwFlags, /* = 0 */
  1947.     INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1948.     LPCTSTR pstrUserName /* = NULL */,
  1949.     LPCTSTR pstrPassword /* = NULL */,
  1950.     DWORD dwContext /* = 1 */)
  1951.     : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1952. {
  1953.     ASSERT(pSession != NULL);
  1954.     ASSERT_KINDOF(CInternetSession, pSession);
  1955. #if defined(_WIN32_WCE)
  1956.     ASSERT( (dwFlags & ~INTERNET_FLAG_SECURE) == 0);
  1957. #else // _WIN32_WCE
  1958.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1959. #endif // _WIN32_WCE
  1960.     ASSERT(AfxIsValidString(pstrServer));
  1961.  
  1962.     m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1963.         nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1964.         dwFlags, m_dwContext);
  1965.  
  1966.     if (m_hConnection == NULL)
  1967.         AfxThrowInternetException(m_dwContext);
  1968.     else
  1969.         _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1970. }
  1971.  
  1972. void CHttpConnection::Close()
  1973. {
  1974.     CInternetConnection::Close();
  1975. }
  1976.  
  1977. CHttpFile* CHttpConnection::OpenRequest(LPCTSTR pstrVerb,
  1978.     LPCTSTR pstrObjectName, LPCTSTR pstrReferer, DWORD dwContext,
  1979.     LPCTSTR* ppstrAcceptTypes, LPCTSTR pstrVersion, DWORD dwFlags)
  1980. {
  1981.     ASSERT_VALID(this);
  1982.     ASSERT(m_hConnection != NULL);
  1983. #if defined(_WIN32_WCE)
  1984.     ASSERT((dwFlags & ~(INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_SECURE)) == 0);
  1985. #else // _WIN32_WCE
  1986.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1987. #endif // _WIN32_WCE
  1988.  
  1989.     if (dwContext == 1)
  1990.         dwContext = m_dwContext;
  1991.  
  1992.     if (pstrVersion == NULL)
  1993.         pstrVersion = HTTP_VERSION;
  1994.  
  1995.     HINTERNET hFile;
  1996.     hFile = HttpOpenRequest(m_hConnection, pstrVerb, pstrObjectName,
  1997.         pstrVersion, pstrReferer, ppstrAcceptTypes, dwFlags, dwContext);
  1998.  
  1999.     CHttpFile* pRet = new CHttpFile(hFile, pstrVerb, pstrObjectName, this);
  2000.     pRet->m_dwContext = dwContext;
  2001.     return pRet;
  2002. }
  2003.  
  2004. CHttpFile* CHttpConnection::OpenRequest(int nVerb,
  2005.     LPCTSTR pstrObjectName, LPCTSTR pstrReferer /* = NULL */, DWORD dwContext,
  2006.     LPCTSTR* ppstrAcceptTypes /* = NULL */,
  2007.     LPCTSTR pstrVersion /* = NULL */, DWORD dwFlags)
  2008. {
  2009.     ASSERT_VALID(this);
  2010.     ASSERT(m_hConnection != NULL);
  2011.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2012.     ASSERT(AfxIsValidString(pstrObjectName));
  2013.  
  2014.     ASSERT(nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX);
  2015.  
  2016.     LPCTSTR pstrVerb;
  2017.     if (nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX)
  2018.         pstrVerb = szHtmlVerbs[nVerb];
  2019.     else
  2020.         pstrVerb = _T("");
  2021.  
  2022.     return OpenRequest(pstrVerb, pstrObjectName, pstrReferer,
  2023.         dwContext, ppstrAcceptTypes, pstrVersion, dwFlags);
  2024. }
  2025.  
  2026. #ifdef _DEBUG
  2027. void CHttpConnection::Dump(CDumpContext& dc) const
  2028. {
  2029.     CInternetConnection::Dump(dc);
  2030.     dc << "\nm_strServerName = " << m_strServerName;
  2031. }
  2032.  
  2033. void CHttpConnection::AssertValid() const
  2034. {
  2035.     ASSERT(m_pSession != NULL);
  2036.     if (m_hConnection != NULL)
  2037.     {
  2038.         ASSERT(AfxGetInternetHandleType(m_hConnection)
  2039.                 == INTERNET_HANDLE_TYPE_CONNECT_HTTP);
  2040.     }
  2041. }
  2042. #endif
  2043.  
  2044.  
  2045. /////////////////////////////////////////////////////////////////////////////
  2046. // CHttpFile
  2047.  
  2048. CHttpFile::CHttpFile(HINTERNET hFile, HINTERNET hSession, LPCTSTR pstrObject,
  2049.     LPCTSTR pstrServer, LPCTSTR pstrVerb, DWORD dwContext)
  2050.  : CInternetFile(hFile, hSession, pstrObject, pstrServer, dwContext, TRUE),
  2051.     m_strVerb(pstrVerb), m_strObject(pstrObject)
  2052. {
  2053.     // caller must set _afxSessionMap!
  2054.     ASSERT(AfxIsValidString(pstrVerb));
  2055. }
  2056.  
  2057.  
  2058. CHttpFile::CHttpFile(HINTERNET hFile, LPCTSTR pstrVerb, LPCTSTR pstrObject,
  2059.     CHttpConnection* pConnection)
  2060.  : CInternetFile(hFile, pstrObject, pConnection, TRUE),
  2061.     m_strVerb(pstrVerb), m_strObject(pstrObject)
  2062. {
  2063.     ASSERT(pstrVerb != NULL);
  2064.     ASSERT(pstrObject != NULL);
  2065.     ASSERT(pConnection != NULL);
  2066.     ASSERT_VALID(pConnection);
  2067. }
  2068.  
  2069. CHttpFile::~CHttpFile()
  2070. {
  2071. }
  2072.  
  2073. void CHttpFile::Close()
  2074. {
  2075.     CInternetFile::Close();
  2076. }
  2077.  
  2078. #if !defined(_WIN32_WCE)
  2079. DWORD CHttpFile::ErrorDlg(CWnd* pParent /* = NULL */,
  2080.     DWORD dwError /* = ERROR_INTERNET_INCORRECT_PASSWORD */,
  2081.     DWORD dwFlags /* = FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS*/,
  2082.     LPVOID* lppvData /* = NULL */)
  2083. {
  2084.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2085.     HWND hWnd;
  2086.     LPVOID lpEmpty;
  2087.     LPVOID* lppvHolder;
  2088.  
  2089.     if (lppvData == NULL)
  2090.     {
  2091.         lpEmpty = NULL;
  2092.         lppvHolder = &lpEmpty;
  2093.     }
  2094.     else
  2095.         lppvHolder = lppvData;
  2096.  
  2097.     if (pParent == NULL || pParent->m_hWnd == NULL)
  2098.         hWnd = GetDesktopWindow();
  2099.     else
  2100.         hWnd = pParent->m_hWnd;
  2101.  
  2102.     return InternetErrorDlg(hWnd, m_hFile, dwError, dwFlags, lppvHolder);
  2103. }
  2104. #endif // _WIN32_WCE
  2105.  
  2106. CString CHttpFile::GetVerb() const
  2107. {
  2108.     ASSERT_VALID(this);
  2109.     ASSERT(m_hFile != NULL);
  2110.  
  2111.     return m_strVerb;
  2112. }
  2113.  
  2114. CString CHttpFile::GetObject() const
  2115. {
  2116.     ASSERT_VALID(this);
  2117.     ASSERT(m_hFile != NULL);
  2118.  
  2119.     return m_strObject;
  2120. }
  2121.  
  2122. CString CHttpFile::GetFileURL() const
  2123. {
  2124.     ASSERT_VALID(this);
  2125.     ASSERT(m_hFile != NULL);
  2126.  
  2127.     CString str(_afxURLhttp);
  2128.     if (m_hConnection != NULL)
  2129.     {
  2130.         str += m_strServerName;
  2131.         int nLen = m_strObject.GetLength();
  2132.         if (nLen > 0)
  2133.         {
  2134.             if (m_strObject[0] != '/' && m_strObject[0] != '\\')
  2135.                 str += '/';
  2136.             str += m_strObject;
  2137.         }
  2138.     }
  2139.  
  2140.     return str;
  2141. }
  2142.  
  2143. BOOL CHttpFile::AddRequestHeaders(LPCTSTR pstrHeaders,
  2144.     DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */,
  2145.     int dwHeadersLen /* = -1 */)
  2146. {
  2147.     ASSERT(AfxIsValidString(pstrHeaders));
  2148.     ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  2149.     ASSERT_VALID(this);
  2150.     ASSERT(m_hFile != NULL);
  2151.  
  2152.     if (dwHeadersLen == -1)
  2153.         if (pstrHeaders == NULL)
  2154.             dwHeadersLen = 0;
  2155.         else
  2156.             dwHeadersLen = lstrlen(pstrHeaders);
  2157.  
  2158.     return HttpAddRequestHeaders(m_hFile, pstrHeaders, dwHeadersLen,
  2159.         dwModifiers);
  2160. }
  2161.  
  2162. BOOL CHttpFile::AddRequestHeaders(CString& str,
  2163.     DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */)
  2164. {
  2165.     return AddRequestHeaders((LPCTSTR) str, dwModifiers, str.GetLength());
  2166. }
  2167.  
  2168. BOOL CHttpFile::SendRequest(LPCTSTR pstrHeaders /* = NULL */,
  2169.     DWORD dwHeadersLen /* = 0 */, LPVOID lpOptional /* = NULL */,
  2170.     DWORD dwOptionalLen /* = 0 */)
  2171. {
  2172.     ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  2173.     ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  2174.     ASSERT_VALID(this);
  2175.     ASSERT(m_hFile != NULL);
  2176.  
  2177.     BOOL bRet = HttpSendRequest(m_hFile,
  2178.         pstrHeaders, dwHeadersLen, lpOptional, dwOptionalLen);
  2179.  
  2180.     if (!bRet)
  2181.         AfxThrowInternetException(m_dwContext);
  2182.  
  2183.     return bRet;
  2184. }
  2185.  
  2186. #if !defined(_WIN32_WCE)
  2187. BOOL CHttpFile::EndRequest(
  2188.     DWORD dwFlags /* = 0 */,
  2189.     LPINTERNET_BUFFERS lpBuffIn /* = NULL */, DWORD dwContext /* = 1 */)
  2190. {
  2191.     ASSERT(m_hFile != NULL);
  2192.     ASSERT(m_bReadMode == -1);
  2193.  
  2194.     if (dwContext == 1)
  2195.         dwContext = m_dwContext;
  2196.  
  2197.     BOOL bRet = HttpEndRequest(m_hFile, lpBuffIn, dwFlags, dwContext);
  2198.  
  2199.     if (!bRet)
  2200.         AfxThrowInternetException(m_dwContext);
  2201.     return bRet;
  2202. }
  2203.  
  2204. BOOL CHttpFile::SendRequestEx(DWORD dwTotalLen,
  2205.     DWORD dwFlags /* = HSR_INITIATE */, DWORD dwContext /* = 1 */)
  2206. {
  2207.     ASSERT(m_hFile != NULL);
  2208.  
  2209.     INTERNET_BUFFERS buffer;
  2210.     memset(&buffer, 0, sizeof(buffer));
  2211.     buffer.dwStructSize = sizeof(buffer);
  2212.     buffer.dwBufferTotal = dwTotalLen;
  2213.  
  2214.     if (dwContext == 1)
  2215.         dwContext = m_dwContext;
  2216.  
  2217.     return SendRequestEx(&buffer, NULL, dwFlags, dwContext);
  2218. }
  2219.  
  2220. BOOL CHttpFile::SendRequestEx(LPINTERNET_BUFFERS lpBuffIn,
  2221.     LPINTERNET_BUFFERS lpBuffOut, DWORD dwFlags /* = HSR_INITIATE */,
  2222.     DWORD dwContext /* = 1 */)
  2223. {
  2224.     ASSERT(m_hFile != NULL);
  2225.     ASSERT_NULL_OR_POINTER(lpBuffIn, INTERNET_BUFFERS);
  2226.     ASSERT_NULL_OR_POINTER(lpBuffOut, INTERNET_BUFFERS);
  2227.  
  2228.     if (dwContext == 1)
  2229.         dwContext = m_dwContext;
  2230.  
  2231.     BOOL bRet = HttpSendRequestEx(m_hFile, lpBuffIn, lpBuffOut,
  2232.         dwFlags, dwContext);
  2233.  
  2234.     if (!bRet)
  2235.         AfxThrowInternetException(m_dwContext);
  2236.  
  2237.     m_bReadMode = -1;
  2238.     return bRet;
  2239. }
  2240. #endif // _WIN32_WCE
  2241.  
  2242. BOOL CHttpFile::SendRequest(CString& strHeaders,
  2243.     LPVOID lpOptional /* = NULL */, DWORD dwOptionalLen /* = 0 */)
  2244. {
  2245.     ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  2246.     ASSERT_VALID(this);
  2247.     ASSERT(m_hFile != NULL);
  2248.  
  2249.     return SendRequest((LPCTSTR) strHeaders, strHeaders.GetLength(),
  2250.         lpOptional, dwOptionalLen);
  2251. }
  2252.  
  2253. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel,
  2254.     LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) const
  2255. {
  2256.     ASSERT((HTTP_QUERY_HEADER_MASK & dwInfoLevel) <= HTTP_QUERY_MAX &&
  2257.         dwInfoLevel != 0);
  2258.     ASSERT(lpvBuffer != NULL && *lpdwBufferLength > 0);
  2259.     ASSERT_VALID(this);
  2260.     ASSERT(m_hFile != NULL);
  2261.  
  2262.     return HttpQueryInfo(m_hFile, dwInfoLevel, lpvBuffer,
  2263.         lpdwBufferLength, lpdwIndex);
  2264. }
  2265.  
  2266. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, DWORD& dwResult,
  2267.     LPDWORD lpdwIndex /* = NULL */) const
  2268. {
  2269.     dwInfoLevel |= HTTP_QUERY_FLAG_NUMBER;
  2270.     DWORD dwDWSize = sizeof(DWORD);
  2271.     return QueryInfo(dwInfoLevel, &dwResult, &dwDWSize, lpdwIndex);
  2272. }
  2273.  
  2274. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, SYSTEMTIME* pSystemTime,
  2275.     LPDWORD lpdwIndex /* = NULL */) const
  2276. {
  2277.     dwInfoLevel |= HTTP_QUERY_FLAG_SYSTEMTIME;
  2278.     DWORD dwTimeSize = sizeof(SYSTEMTIME);
  2279.     return QueryInfo(dwInfoLevel, pSystemTime, &dwTimeSize, lpdwIndex);
  2280. }
  2281.  
  2282. BOOL CHttpFile::QueryInfoStatusCode(DWORD& dwStatusCode) const
  2283. {
  2284.     ASSERT_VALID(this);
  2285.     ASSERT(m_hFile != NULL);
  2286.  
  2287.     TCHAR szBuffer[80];
  2288.     DWORD dwLen = _countof(szBuffer);
  2289.     BOOL bRet;
  2290.  
  2291.     bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE,
  2292.                 szBuffer, &dwLen, NULL);
  2293.  
  2294.     if (bRet)
  2295.         dwStatusCode = (DWORD) _ttol(szBuffer);
  2296.     return bRet;
  2297. }
  2298.  
  2299. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, CString& str,
  2300.     LPDWORD lpdwIndex) const
  2301. {
  2302.     ASSERT(dwInfoLevel <= HTTP_QUERY_MAX && dwInfoLevel >= 0);
  2303.     ASSERT_VALID(this);
  2304.     ASSERT(m_hFile != NULL);
  2305.  
  2306.     BOOL bRet;
  2307.     DWORD dwLen = 0;
  2308.  
  2309.     // ask for nothing to see how long the return really is
  2310.  
  2311.     str.Empty();
  2312.     if (HttpQueryInfo(m_hFile, dwInfoLevel, NULL, &dwLen, 0))
  2313.         bRet = TRUE;
  2314.     else
  2315.     {
  2316.         // now that we know how long it is, ask for exactly that much
  2317.         // space and really request the header from the API
  2318.  
  2319.         LPTSTR pstr = str.GetBufferSetLength(dwLen);
  2320.         bRet = HttpQueryInfo(m_hFile, dwInfoLevel, pstr, &dwLen, lpdwIndex);
  2321.         if (bRet)
  2322.             str.ReleaseBuffer(dwLen);
  2323.         else
  2324.             str.ReleaseBuffer(0);
  2325.     }
  2326.  
  2327.     return bRet;
  2328. }
  2329.  
  2330. #ifdef _DEBUG
  2331. void CHttpFile::Dump(CDumpContext& dc) const
  2332. {
  2333.     dc << "\nm_strFileName = " << m_strFileName;
  2334.     dc << "\nm_strVerb = " << m_strVerb;
  2335. }
  2336.  
  2337. void CHttpFile::AssertValid() const
  2338. {
  2339.     CInternetFile::AssertValid();
  2340. }
  2341. #endif
  2342.  
  2343. #if !defined(_WIN32_WCE)
  2344. /////////////////////////////////////////////////////////////////////////////
  2345. // CGopherFile
  2346.  
  2347. CGopherFile::CGopherFile(HINTERNET hFile, CGopherLocator& refLocator,
  2348.     CGopherConnection* pConnection)
  2349.     : CInternetFile(hFile, _T(""), pConnection, TRUE),
  2350.         m_Locator(refLocator)
  2351. {
  2352.     ASSERT(pConnection != NULL);
  2353.     ASSERT_VALID(pConnection);
  2354. }
  2355.  
  2356. CGopherFile::CGopherFile(HINTERNET hFile, HINTERNET hSession,
  2357.     LPCTSTR pstrLocator, DWORD dwLocLen, DWORD dwContext)
  2358.     : CInternetFile(hFile, hSession, _T(""), _T(""), dwContext, TRUE),
  2359.         m_Locator(pstrLocator, dwLocLen)
  2360. {
  2361.     // caller muset set _afxSessionMap!
  2362. }
  2363.  
  2364. CGopherFile::~CGopherFile()
  2365. {
  2366. }
  2367.  
  2368. void CGopherFile::Close()
  2369. {
  2370.     CInternetFile::Close();
  2371. }
  2372.  
  2373. void CGopherFile::Write(const void* lpBuf, UINT nCount)
  2374. {
  2375.     UNUSED_ALWAYS(lpBuf);
  2376.     UNUSED_ALWAYS(nCount);
  2377.  
  2378.     ASSERT(FALSE);
  2379.     AfxThrowNotSupportedException();
  2380. }
  2381.  
  2382. void CGopherFile::WriteString(LPCTSTR pstr)
  2383. {
  2384.     UNUSED_ALWAYS(pstr);
  2385.  
  2386.     ASSERT(FALSE);
  2387.     AfxThrowNotSupportedException();
  2388. }
  2389.  
  2390. #ifdef _DEBUG
  2391. void CGopherFile::Dump(CDumpContext& dc) const
  2392. {
  2393.     CInternetFile::Dump(dc);
  2394. }
  2395.  
  2396. void CGopherFile::AssertValid() const
  2397. {
  2398.     CInternetFile::AssertValid();
  2399. }
  2400. #endif
  2401.  
  2402. #endif // _WIN32_WCE
  2403. #if !defined(_WIN32_WCE_NO_FTP)
  2404. /////////////////////////////////////////////////////////////////////////////
  2405. // CFtpFileFind
  2406.  
  2407. CFtpFileFind::CFtpFileFind(CFtpConnection* pConnection, DWORD dwContext)
  2408. {
  2409.     ASSERT(pConnection != NULL);
  2410.     ASSERT_KINDOF(CFtpConnection, pConnection);
  2411.  
  2412.     m_pConnection = pConnection;
  2413.     if (dwContext == 1)
  2414.         dwContext = pConnection->GetContext();
  2415.     m_dwContext = dwContext;
  2416.     m_chDirSeparator = '/';
  2417. }
  2418.  
  2419. CFtpFileFind::~CFtpFileFind()
  2420. {
  2421. }
  2422.  
  2423. BOOL CFtpFileFind::FindFile(LPCTSTR pstrName /* = NULL */,
  2424.     DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2425. {
  2426.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2427.     ASSERT(m_pConnection != NULL);
  2428.     ASSERT_VALID(m_pConnection);
  2429.  
  2430.     if (m_pConnection == NULL)
  2431.         return FALSE;
  2432.  
  2433.     Close();
  2434.     m_pNextInfo = new WIN32_FIND_DATA;
  2435.     m_bGotLast = FALSE;
  2436.  
  2437.     if (pstrName == NULL)
  2438.         pstrName = _T("*");
  2439.     lstrcpy(((LPWIN32_FIND_DATA) m_pNextInfo)->cFileName, pstrName);
  2440.  
  2441.     m_hContext = FtpFindFirstFile((HINTERNET) *m_pConnection,
  2442.         pstrName, (LPWIN32_FIND_DATA) m_pNextInfo, dwFlags, m_dwContext);
  2443.  
  2444.     if (m_hContext == NULL)
  2445.     {
  2446.         Close();
  2447.         return FALSE;
  2448.     }
  2449.  
  2450.     LPCTSTR pstrRoot = _tcspbrk(pstrName, _T("\\/"));
  2451.     CString strCWD;
  2452.     m_pConnection->GetCurrentDirectory(strCWD);
  2453.  
  2454.     if (pstrRoot == NULL)
  2455.     {
  2456.         if (m_pConnection->SetCurrentDirectory(pstrName))
  2457.         {
  2458.             m_pConnection->GetCurrentDirectory(m_strRoot);
  2459.             m_pConnection->SetCurrentDirectory(strCWD);
  2460.         }
  2461.         else
  2462.             m_strRoot = strCWD;
  2463.     }
  2464.     else
  2465.     {
  2466.         // find the last forward or backward whack
  2467.  
  2468.         int nLast;
  2469.         LPCTSTR pstrOther = _tcsrchr(pstrName, '\\');
  2470.         pstrRoot = _tcsrchr(pstrName, '/');
  2471.  
  2472.         if (pstrRoot == NULL)
  2473.             pstrRoot = pstrName;
  2474.         if (pstrOther == NULL)
  2475.             pstrOther = pstrName;
  2476.  
  2477.         if (pstrRoot >= pstrOther)
  2478.             nLast = pstrRoot - pstrName;
  2479.         else
  2480.             nLast = pstrOther - pstrName;
  2481.  
  2482.         // from the start to the last whack is the root
  2483.  
  2484.         if (nLast == 0)
  2485.             nLast++;
  2486.  
  2487.         m_strRoot = pstrName;
  2488.         m_strRoot = m_strRoot.Left(nLast);
  2489.     }
  2490.  
  2491.     return TRUE;
  2492. }
  2493.  
  2494. BOOL CFtpFileFind::FindNextFile()
  2495. {
  2496.     ASSERT(m_hContext != NULL);
  2497.     if (m_hContext == NULL)
  2498.         return FALSE;
  2499.  
  2500.     if (m_pFoundInfo == NULL)
  2501.         m_pFoundInfo = new WIN32_FIND_DATA;
  2502.  
  2503.     ASSERT_VALID(this);
  2504.     void* pTemp = m_pFoundInfo;
  2505.     m_pFoundInfo = m_pNextInfo;
  2506.     m_pNextInfo = pTemp;
  2507.  
  2508.     return InternetFindNextFile(m_hContext, m_pNextInfo);
  2509. }
  2510.  
  2511. void CFtpFileFind::CloseContext()
  2512. {
  2513.     if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  2514.     {
  2515.         InternetCloseHandle(m_hContext);
  2516.         m_hContext = NULL;
  2517.     }
  2518.  
  2519.     return;
  2520. }
  2521.  
  2522. CString CFtpFileFind::GetFileURL() const
  2523. {
  2524.     ASSERT_VALID(this);
  2525.     ASSERT(m_hContext != NULL);
  2526.  
  2527.     CString str;
  2528.  
  2529.     if (m_hContext != NULL)
  2530.     {
  2531.         str += _afxURLftp;
  2532.         str += m_pConnection->GetServerName();
  2533.         str += GetFilePath();
  2534.     }
  2535.  
  2536.     return str;
  2537. }
  2538.  
  2539. #ifdef _DEBUG
  2540. void CFtpFileFind::Dump(CDumpContext& dc) const
  2541. {
  2542.     CFileFind::Dump(dc);
  2543.     dc << "m_hContext = " << m_hContext;
  2544. }
  2545.  
  2546. void CFtpFileFind::AssertValid() const
  2547. {
  2548.     CFileFind::AssertValid();
  2549. }
  2550. #endif
  2551.  
  2552.  
  2553. #endif // _WIN32_WCE_NO_FTP
  2554. #if !defined(_WIN32_WCE)
  2555. /////////////////////////////////////////////////////////////////////////////
  2556. // CGopherFileFind
  2557.  
  2558. CGopherFileFind::CGopherFileFind(CGopherConnection* pConnection,
  2559.     DWORD dwContext)
  2560. {
  2561.     ASSERT(pConnection != NULL);
  2562.     ASSERT_KINDOF(CGopherConnection, pConnection);
  2563.  
  2564.     m_pConnection = pConnection;
  2565.     if (dwContext == 1)
  2566.         dwContext = pConnection->GetContext();
  2567.     m_dwContext = dwContext;
  2568. }
  2569.  
  2570. CGopherFileFind::~CGopherFileFind()
  2571. {
  2572. }
  2573.  
  2574. BOOL CGopherFileFind::FindFile(LPCTSTR pstrString,
  2575.     DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2576. {
  2577.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2578.     Close();
  2579.  
  2580.     m_pNextInfo = new GOPHER_FIND_DATA;
  2581.     m_bGotLast = FALSE;
  2582.  
  2583.     m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2584.         NULL, pstrString,
  2585.         (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2586.  
  2587.     if (m_hContext == NULL)
  2588.         Close();
  2589.     return (m_hContext != NULL);
  2590. }
  2591.  
  2592. BOOL CGopherFileFind::FindFile(CGopherLocator& refLocator,
  2593.     LPCTSTR pstrString, DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2594. {
  2595.     ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2596.     Close();
  2597.  
  2598.     m_pNextInfo = new GOPHER_FIND_DATA;
  2599.     m_pFoundInfo = new GOPHER_FIND_DATA;
  2600.     m_bGotLast = FALSE;
  2601.  
  2602.     m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2603.         (LPCTSTR) refLocator, pstrString,
  2604.         (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2605.  
  2606.     if (m_hContext == NULL)
  2607.         Close();
  2608.     return (m_hContext != NULL);
  2609. }
  2610.  
  2611. BOOL CGopherFileFind::FindNextFile()
  2612. {
  2613.     ASSERT(m_hContext != NULL);
  2614.     if (m_hContext == NULL)
  2615.         return FALSE;
  2616.  
  2617.     if (m_pFoundInfo == NULL)
  2618.         m_pFoundInfo = new GOPHER_FIND_DATA;
  2619.  
  2620.     ASSERT_VALID(this);
  2621.     void* pTemp = m_pFoundInfo;
  2622.     m_pFoundInfo = m_pNextInfo;
  2623.     m_pNextInfo = pTemp;
  2624.  
  2625.     return InternetFindNextFile(m_hContext, m_pNextInfo);
  2626. }
  2627.  
  2628. void CGopherFileFind::CloseContext()
  2629. {
  2630.     if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  2631.     {
  2632.         InternetCloseHandle(m_hContext);
  2633.         m_hContext = NULL;
  2634.     }
  2635.  
  2636.     return;
  2637. }
  2638.  
  2639. CString CGopherFileFind::GetFileName() const
  2640. {
  2641.     AfxThrowNotSupportedException();
  2642.     return CString();
  2643. }
  2644.  
  2645. CString CGopherFileFind::GetFilePath() const
  2646. {
  2647.     AfxThrowNotSupportedException();
  2648.     return CString();
  2649. }
  2650.  
  2651. CString CGopherFileFind::GetFileTitle() const
  2652. {
  2653.     AfxThrowNotSupportedException();
  2654.     return CString();
  2655. }
  2656.  
  2657. BOOL CGopherFileFind::IsDots() const
  2658. {
  2659.     // gophers never have dots
  2660.     return FALSE;
  2661. }
  2662.  
  2663. BOOL CGopherFileFind::GetLastWriteTime(FILETIME* pTimeStamp) const
  2664. {
  2665.     ASSERT(m_hContext != NULL);
  2666.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2667.     ASSERT_VALID(this);
  2668.  
  2669.     if (m_pFoundInfo != NULL && pTimeStamp != NULL)
  2670.     {
  2671.         *pTimeStamp = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime;
  2672.         return TRUE;
  2673.     }
  2674.     else
  2675.         return FALSE;
  2676. }
  2677.  
  2678. BOOL CGopherFileFind::GetLastAccessTime(FILETIME* pTimeStamp) const
  2679. {
  2680.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2681.     return GetLastWriteTime(pTimeStamp);
  2682. }
  2683.  
  2684. BOOL CGopherFileFind::GetCreationTime(FILETIME* pTimeStamp) const
  2685. {
  2686.     ASSERT_POINTER(pTimeStamp, FILETIME);
  2687.     return GetLastWriteTime(pTimeStamp);
  2688. }
  2689.  
  2690. BOOL CGopherFileFind::GetLastWriteTime(CTime& refTime) const
  2691. {
  2692.     ASSERT(m_hContext != NULL);
  2693.     ASSERT_VALID(this);
  2694.  
  2695.     if (m_pFoundInfo != NULL)
  2696.     {
  2697.         refTime = CTime(((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime);
  2698.         return TRUE;
  2699.     }
  2700.     else
  2701.         return FALSE;
  2702. }
  2703.  
  2704. BOOL CGopherFileFind::GetCreationTime(CTime& refTime) const
  2705. {
  2706.     return GetLastWriteTime(refTime);
  2707. }
  2708.  
  2709. BOOL CGopherFileFind::GetLastAccessTime(CTime& refTime) const
  2710. {
  2711.     return GetLastWriteTime(refTime);
  2712. }
  2713.  
  2714.  
  2715. CString CGopherFileFind::GetFileURL() const
  2716. {
  2717.     AfxThrowNotSupportedException();
  2718.     return CString();
  2719. }
  2720.  
  2721. CString CGopherFileFind::GetRoot() const
  2722. {
  2723.     AfxThrowNotSupportedException();
  2724.     return CString();
  2725. }
  2726.  
  2727. CGopherLocator CGopherFileFind::GetLocator() const
  2728. {
  2729.     ASSERT_VALID(this);
  2730.     ASSERT(m_pConnection != NULL && m_hContext != NULL);
  2731.  
  2732.     return m_pConnection->CreateLocator(
  2733.         ((LPGOPHER_FIND_DATA) m_pFoundInfo)->Locator);
  2734. }
  2735.  
  2736. CString CGopherFileFind::GetScreenName() const
  2737. {
  2738.     ASSERT_VALID(this);
  2739.     ASSERT(m_hContext != NULL);
  2740.  
  2741.     CString str;
  2742.  
  2743.     if (m_pFoundInfo != NULL)
  2744.         str = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->DisplayString;
  2745.  
  2746.     return str;
  2747. }
  2748.  
  2749. DWORD CGopherFileFind::GetLength() const
  2750. {
  2751.     ASSERT_VALID(this);
  2752.  
  2753.     if (m_pFoundInfo != NULL)
  2754.         return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow;
  2755.     else
  2756.         return 0;
  2757. }
  2758.  
  2759. #if defined(_X86_) || defined(_ALPHA_)
  2760. __int64 CGopherFileFind::GetLength64() const
  2761. {
  2762.     ASSERT_VALID(this);
  2763.  
  2764.     if (m_pFoundInfo != NULL)
  2765.         return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow +
  2766.                 (((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeHigh << 32);
  2767.     else
  2768.         return 0;
  2769. }
  2770. #endif
  2771.  
  2772. #ifdef _DEBUG
  2773. void CGopherFileFind::Dump(CDumpContext& dc) const
  2774. {
  2775.     CFileFind::Dump(dc);
  2776.     dc << "m_hContext = " << m_hContext;
  2777. }
  2778.  
  2779. void CGopherFileFind::AssertValid() const
  2780. {
  2781.     CFileFind::AssertValid();
  2782. }
  2783. #endif
  2784.  
  2785.  
  2786. /////////////////////////////////////////////////////////////////////////////
  2787. // CGopherLocator
  2788.  
  2789. CGopherLocator::CGopherLocator(LPCTSTR pstrLocator, DWORD dwLocLen)
  2790. {
  2791.     ASSERT(AfxIsValidString(pstrLocator));
  2792.     LPTSTR pstr = m_Locator.GetBufferSetLength(dwLocLen);
  2793.     memcpy(pstr, pstrLocator, dwLocLen);
  2794.     m_Locator.ReleaseBuffer(dwLocLen);
  2795.     m_dwBufferLength = dwLocLen;
  2796. }
  2797.  
  2798. CGopherLocator::~CGopherLocator()
  2799. {
  2800. }
  2801. #endif // _WIN32_WCE
  2802.  
  2803. /////////////////////////////////////////////////////////////////////////////
  2804. // exception handling
  2805.  
  2806. void AFXAPI AfxThrowInternetException(DWORD dwContext, DWORD dwError /* = 0 */)
  2807. {
  2808.     if (dwError == 0)
  2809.         dwError = ::GetLastError();
  2810.  
  2811.     CInternetException* pException = new CInternetException(dwError);
  2812.     pException->m_dwContext = dwContext;
  2813.  
  2814.     TRACE1("Warning: throwing CInternetException for error %d\n", dwError);
  2815.     THROW(pException);
  2816. }
  2817.  
  2818.  
  2819. BOOL CInternetException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError,
  2820.         PUINT pnHelpContext)
  2821. {
  2822.     ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
  2823.  
  2824.     if (pnHelpContext != NULL)
  2825.         *pnHelpContext = 0;
  2826.  
  2827.     LPTSTR lpBuffer;
  2828.     BOOL bRet = TRUE;
  2829.  
  2830.     HINSTANCE hWinINetLibrary;
  2831.     hWinINetLibrary = ::WCE_FCTN(LoadLibraryA)(WCE_IF(WCE_WININET_DLL,"WININET.DLL"));
  2832.  
  2833.     if (hWinINetLibrary == NULL ||
  2834.         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  2835.             hWinINetLibrary, m_dwError,
  2836.             MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2837.             (LPTSTR) &lpBuffer, 0, NULL) == 0)
  2838.     {
  2839.         // it failed! try Windows...
  2840.  
  2841.         bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  2842.             NULL,  m_dwError,
  2843.             MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2844.             (LPTSTR) &lpBuffer, 0, NULL);
  2845.     }
  2846.  
  2847.     if (!bRet)
  2848.         *pstrError = '\0';
  2849.     else
  2850.     {
  2851.         if (m_dwError == ERROR_INTERNET_EXTENDED_ERROR)
  2852.         {
  2853.             LPTSTR lpExtended;
  2854.             DWORD dwLength = 0;
  2855.             DWORD dwError;
  2856.  
  2857.             // find the length of the error
  2858.             if (!InternetGetLastResponseInfo(&dwError, NULL, &dwLength) &&
  2859.                 GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2860.             {
  2861.                 lpExtended = (LPTSTR) LocalAlloc(LPTR, dwLength);
  2862.                 InternetGetLastResponseInfo(&dwError, lpExtended, &dwLength);
  2863.                 lstrcpyn(pstrError, lpExtended, nMaxError);
  2864.                 pstrError += dwLength;
  2865.                 nMaxError -= dwLength;
  2866.                 if (nMaxError < 0)
  2867.                     nMaxError = 0;
  2868.                 LocalFree(lpExtended);
  2869.             }
  2870.             else
  2871.                 TRACE0("Warning: Extended error reported with no response info\n");
  2872.             bRet = TRUE;
  2873.         }
  2874.         else
  2875.         {
  2876.             lstrcpyn(pstrError, lpBuffer, nMaxError);
  2877.             bRet = TRUE;
  2878.         }
  2879.  
  2880.         LocalFree(lpBuffer);
  2881.     }
  2882.  
  2883. #ifndef _AFXDLL
  2884.     ::FreeLibrary(hWinINetLibrary);
  2885. #endif
  2886.     return bRet;
  2887. }
  2888.  
  2889. CInternetException::CInternetException(DWORD dwError)
  2890. {
  2891.     m_dwError = dwError;
  2892. }
  2893.  
  2894. CInternetException::~CInternetException()
  2895. {
  2896. }
  2897.  
  2898. #ifdef _DEBUG
  2899. void CInternetException::Dump(CDumpContext& dc) const
  2900. {
  2901.     CObject::Dump(dc);
  2902.  
  2903.     dc << "m_dwError = " << m_dwError;
  2904.     dc << "\nm_dwContext = " << m_dwContext;
  2905. }
  2906. #endif
  2907.  
  2908. /////////////////////////////////////////////////////////////////////////////
  2909. // Inline function declarations expanded out-of-line
  2910.  
  2911. #ifndef _AFX_ENABLE_INLINES
  2912.  
  2913. // expand inlines for OLE dialog APIs
  2914. static char _szAfxInetInl[] = "afxinet.inl";
  2915. #undef THIS_FILE
  2916. #define THIS_FILE _szAfxInetInl
  2917. #define _AFXINET_INLINE
  2918. #include "afxinet.inl"
  2919.  
  2920. #endif //!_AFX_ENABLE_INLINES
  2921.  
  2922. /////////////////////////////////////////////////////////////////////////////
  2923. // Pre-startup code
  2924.  
  2925. #ifdef AFX_INIT_SEG
  2926. #pragma code_seg(AFX_INIT_SEG)
  2927. #endif
  2928.  
  2929. IMPLEMENT_DYNAMIC(CInternetException, CException)
  2930. IMPLEMENT_DYNAMIC(CInternetFile, CStdioFile)
  2931. IMPLEMENT_DYNAMIC(CHttpFile, CInternetFile)
  2932. WCE_DEL IMPLEMENT_DYNAMIC(CGopherFile, CInternetFile)
  2933. IMPLEMENT_DYNAMIC(CInternetSession, CObject)
  2934. IMPLEMENT_DYNAMIC(CInternetConnection, CObject)
  2935. #if !defined(_WIN32_WCE_NO_FTP)
  2936. IMPLEMENT_DYNAMIC(CFtpConnection, CInternetConnection)
  2937. #endif // _WIN32_WCE_NO_FTP
  2938. IMPLEMENT_DYNAMIC(CHttpConnection, CInternetConnection)
  2939. WCE_DEL IMPLEMENT_DYNAMIC(CGopherConnection, CInternetConnection)
  2940. #if !defined(_WIN32_WCE_NO_FTP)
  2941. IMPLEMENT_DYNAMIC(CFtpFileFind, CFileFind)
  2942. #endif // _WIN32_WCE_NO_FTP
  2943. WCE_DEL IMPLEMENT_DYNAMIC(CGopherFileFind, CFileFind)
  2944.  
  2945. #pragma warning(disable: 4074)
  2946. #pragma init_seg(compiler)
  2947.  
  2948. CSessionMapPtrToPtr _afxSessionMap;
  2949. #endif // _WIN32_WCE_NO_WININET
  2950.  
  2951.